springboot综合案例第三课
SpringSecurity入门
什么是SpringSecurity
Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。
(https://projects.spring.io/spring-security/) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别
是使用领先的J2EE解决方案-Spring框架开发的企业软件项目。人们使用Spring Security有很多种原因,不过通常吸
引他们的是在J2EE Servlet规范或EJB规范中找不到典型企业应用场景的解决方案。特别要指出的是他们不能再
WAR 或 EAR 级别进行移植。这样,如果你更换服务器环境,就要,在新的目标环境进行大量的工作,对你的应用
系统进行重新配置安全。使用Spring Security 解决了这些问题,也为你提供很多有用的,完全可以指定的其他安
全特性。安全包括两个主要操作。
- “认证”,是为用户建立一个他所声明的主体。主题一般式指用户,设备或可以在你系统中执行动作的其他系
统。(简单来说:系统认为用户是否能登录)
- “授权”,指的是一个用户能否在你的应用中执行某个操作,在到达授权判断之前,身份的主题已经由身份验证
过程建立了。(简单来说:系统判断用户是否有权限去做某些事情)
这些概念是通用的,不是Spring Security特有的。在身份验证层面,Spring Security广泛支持各种身份验证模式,
这些验证模型绝大多数都由第三方提供,或则正在开发的有关标准机构提供的,例如 Internet Engineering Task
Force.作为补充,Spring Security 也提供了自己的一套验证功能。
Spring Security 目前支持认证一体化如下认证技术: HTTP BASIC authentication headers (一个基于IEFT RFC 的
标准) HTTP Digest authentication headers (一个基于IEFT RFC 的标准) HTTP X.509 client certi?cate exchange
(一个基于IEFT RFC 的标准) LDAP (一个非常常见的跨平台认证需要做法,特别是在大环境) Form-based
authentication (提供简单用户接口的需求) OpenID authentication Computer Associates Siteminder JA-SIG
Central Authentication Service (CAS,这是一个流行的开源单点登录系统) Transparent authentication context
propagation for Remote Method Invocation and HttpInvoker (一个Spring远程调用协议)
用户登录认证
表结构分析与创建
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GnUk2Dvg-1692278828416)(day03_springboot综合案例.assets/image-20210516220645141.png)]
-- 用户表
CREATE TABLE users(id VARCHAR(32) PRIMARY KEY,email VARCHAR(50) UNIQUE NOT NULL,username VARCHAR(50),PASSWORD VARCHAR(100),phoneNum VARCHAR(20),STATUS INT
);-- 角色表
CREATE TABLE role(id VARCHAR(32) PRIMARY KEY,roleName VARCHAR(50) ,roleDesc VARCHAR(50)
);-- 用户角色关联表
CREATE TABLE users_role(userId VARCHAR(32),roleId VARCHAR(32),PRIMARY KEY(userId,roleId),FOREIGN KEY (userId) REFERENCES users(id),FOREIGN KEY (roleId) REFERENCES role(id)
);-- 资源权限表
CREATE TABLE permission(id VARCHAR(32) PRIMARY KEY,permissionName VARCHAR(50) ,url VARCHAR(50)
);-- 角色权限关联表
CREATE TABLE role_permission(permissionId VARCHAR(32),roleId VARCHAR(32),PRIMARY KEY(permissionId,roleId),FOREIGN KEY (permissionId) REFERENCES permission(id),FOREIGN KEY (roleId) REFERENCES role(id)
);
创建类
创建UserInfo
@Data
public class UserInfo {private String id;private String username;private String email;private String password;private String phoneNum;private int status;private String statusStr;private List<Role> roles;
}
创建Role
@Data
public class Role {private String id;private String roleName;private String roleDesc;private List<Permission> permissions;private List<UserInfo> users;
}
创建Permission
@Data
public class Permission {private String id;private String permissionName;private String url;private List<Role> roles;
}
Spring Security数据库认证底层
在Spring Security中如果想要使用数据进行认证操作,有很多种操作方式,这里我们介绍使用UserDetails、
UserDetailsService来完成操作。
-
UserDetails
public interface UserDetails extends Serializable {Collection<? extends GrantedAuthority> getAuthorities();String getPassword();String getUsername();boolean isAccountNonExpired();boolean isAccountNonLocked();boolean isCredentialsNonExpired();boolean isEnabled(); }
UserDatails是一个接口,我们可以认为UserDetails作用是于封装当前进行认证的用户信息,但由于其是一个
接口,所以我们可以对其进行实现,也可以使用Spring Security提供的一个UserDetails的实现类User来完成
操作,Ctrl+Alt+B 查找接口实现类
以下是User类的部分代码
public class User implements UserDetails, CredentialsContainer {private String password;private final String username;private final Set<GrantedAuthority> authorities;private final boolean accountNonExpired; //帐户是否过期private final boolean accountNonLocked; //帐户是否锁定private final boolean credentialsNonExpired; //认证是否过期 private final boolean enabled; //帐户是否可用 }
-
UserDetailsService
public interface UserDetailsService {UserDetails loadUserByUsername(String username) throws UsernameNotFoundException; }
上面将UserDetails与UserDetailsService做了一个简单的介绍,那么我们具体如何完成Spring Security的数据库认
证操作,我们通过用户管理中用户登录来完成Spring Security的认证操作。
用户登录流程分析
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KG7Pu1wO-1692278828417)(assets/image-20201012180237425.png)]
登录认证
添加依赖
<!--SpringSecurity--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId></dependency>
Spring Security配置类
package cn.yanqi.config;import cn.yanqi.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import javax.annotation.Resource;// @EnableGlobalMethodSecurity(jsr250Enabled = true) //开启jsr250注解
// @EnableGlobalMethodSecurity(securedEnabled = true) //开启secured注解
// @EnableGlobalMethodSecurity(prePostEnabled = true) //开启表达式注解
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Resourceprivate UserService userService;@Overrideprotected void configure(HttpSecurity http) throws Exception {//自定义表单登录页面http.formLogin()//指定登录页面.loginPage("/to/login")//指定登录请求.loginProcessingUrl("/login").usernameParameter("username").passwordParameter("password").successForwardUrl("/to/index").failureUrl("/to/failer").and().logout().logoutUrl("/logout").logoutSuccessUrl("/to/login").invalidateHttpSession(true) //是否清除session.and()//权限配置.authorizeRequests()//放行 登录页面.antMatchers("/to/login","/to/failer").permitAll()//放开 静态资源.antMatchers("/css/**","/img/**","/js/**","/plugins/**").permitAll()//其他 资源需要登录后访问.anyRequest().authenticated().and()//禁用csrf.csrf().disable();//没有权限http.exceptionHandling().accessDeniedPage("/to/403");}//认证的数据需要使用自定义的UserDetailsService@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService).passwordEncoder(passwordEncoder());}@Beanpublic PasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}
}
编写UserService
package cn.yanqi.service;import org.springframework.security.core.userdetails.UserDetailsService;
//继承 UserDetailsService 重写loadUserByUsername 完成认证
public interface UserService extends UserDetailsService {}
import cn.yanqi.travel.mapper.UserMapper;
import cn.yanqi.travel.pojo.Role;
import cn.yanqi.travel.pojo.UserInfo;
import cn.yanqi.travel.service.UserService;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;@Service
public class UserServiceImpl implements UserService {@Resourceprivate UserMapper userMapper;@Resourceprivate PasswordEncoder passwordEncoder;/*** 认证--查询用户* @param s* @return* @throws UsernameNotFoundException*/@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {UserInfo userInfo = this.userMapper.findUserByUserName(s);User user = new User(userInfo.getUsername(),userInfo.getPassword(),userInfo.getStatus() == 0 ? false : true,//校验用户是否开启true, //帐号是否过期 不过期true, //证号 不过期true, //帐号 不锁定getAuthority(userInfo.getRoles()));System.out.println("用户:"+userInfo.getUsername());System.out.println("=======================");return user;}/*** 认证--查询用户对应的角色*/private List<SimpleGrantedAuthority> getAuthority(List<Role> roles) {List<SimpleGrantedAuthority> list = new ArrayList<>();for(Role role : roles){System.out.println("对应角色:"+role.getRoleName());list.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName()));}return list;}
}
编写UserMapper
public interface UserMapper {/*** 通过用户名查询用户* @param s* @return*/UserInfo findUserByUserName(String s);
}
编写UserMapper.xml
<!--登录认证:通过用户名查询用户--><resultMap id="userresultMap" type="UserInfo" autoMapping="true"><id property="id" column="id"/><collection property="roles" ofType="Role" javaType="List" autoMapping="true"><id property="id" column="rid"/></collection></resultMap><select id="findUserByUserName" resultMap="userresultMap">SELECT*,r.id ridFROMusers u,role r,users_role urWHEREu.id = ur.userId ANDr.id = ur.roleId ANDu.username = #{s}</select>
注意事项:如果登录认证提交出现405,是因为通用页面跳转是@GetMapping, Security的登录后台跳转需要post请求
把通用页面跳转改为@RequestMapping(“{page}”)即可
测试
登录认证-把users表中的status状态修改 0和1进行测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-64TQouaV-1692278828419)(day03_springboot综合案例.assets/image-20210517223706124.png)]
权限控制
Spring Security配置类
// @EnableGlobalMethodSecurity(jsr250Enabled = true) //开启jsr250注解
// @EnableGlobalMethodSecurity(securedEnabled = true) //开启secured注解
// @EnableGlobalMethodSecurity(prePostEnabled = true) //开启表达式注解
@EnableWebSecurity
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {//Spring Security配置类
}
代码实现
基于方法级别权限控制,有三种方式
/*** 查询所有产品* @param page* @param size* @return*/// @RolesAllowed({"ADMIN","USER"}) // JSR-250注解// @RolesAllowed("ADMIN") // JSR-250注解// @Secured("ROLE_ADMIN") // Secured注解// @PreAuthorize("authentication.principal.username == 'jack'")//只有jack才可以访问@RequestMapping("findAll")public String findAll( Model model,@RequestParam(value = "page",defaultValue = "1") Integer page,@RequestParam(value = "size",defaultValue = "5") Integer size){PageHelper.startPage(page,size);List<Product> productList = this.productService.findAll();PageInfo pageInfo = new PageInfo(productList);model.addAttribute("pageInfo", pageInfo);return "product-list";}
uestMapping(“findAll”)
public String findAll( Model model,
@RequestParam(value = “page”,defaultValue = “1”) Integer page,
@RequestParam(value = “size”,defaultValue = “5”) Integer size){
PageHelper.startPage(page,size);List<Product> productList = this.productService.findAll();PageInfo pageInfo = new PageInfo(productList);model.addAttribute("pageInfo", pageInfo);return "product-list";
}
相关文章:

springboot综合案例第三课
SpringSecurity入门 什么是SpringSecurity Spring Security 的前身是 Acegi Security ,是 Spring 项目组中用来提供安全认证服务的框架。 (https://projects.spring.io/spring-security/) Spring Security 为基于J2EE企业应用软件提供了全面安全服务。特别 是使…...

面试经典150题——罗马数字转整数
罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#x…...

第三篇|金融人数据来源有哪些
数据对于金融行业真的很重要,那么金融人有哪些途径查数据呢? 国内: 1. 国家统计局 这个应该是无论什么行业都使用最频繁的网站,每个月都会固定发上个月资产投资数据 、工业增加值和利润数据等常规数据,其他数据也会…...

爬虫逆向实战(二)--某某观察城市排行榜
一、数据接口分析 主页地址:某某观察 1、抓包 通过抓包可以发现数据接口是multi 2、判断是否有加密参数 请求参数是否加密? 无请求头是否加密? 无cookie是否加密? 无响应数据是否加密? 通过查看“响应”板块可以…...

Grafana Prometheus 通过JMX监控kafka 【2023最新方式】
第三方kafka exporter方案 目前网上关于使用Prometheus 监控kafka的大部分资料都是使用一个第三方的 kafka exporter,他的原理大概就是启动一个kafka客户端,获取kafka服务器的信息,然后提供一些metric接口供Prometheus使用,随意它…...

发布游戏,进行打包。(Unity)
做到这里,我们的项目基本功能已经完成了,如果你还想使项目功能更加完善,可以自己思考如何补充,充分发挥并进行优化使效果达到更加美好。 首先呢,我们这里是说打包Window电脑游戏,我们直接点击菜单栏文件-&…...

我的C++待办事项
2023年8月17日 内存管理部分 学习智能指针 写一篇关于怎么在Linux中安装和使用vclgrind的博客(2023年8月17日下午完成) 拍一个关于在Linux中安装和使用vclgrind的视频 在Windows上怎么检测内存泄漏 怎么使用Address Sanitizer 在Linux上如何使用gc…...

浙大数据结构第七周之Saving James Bond - Hard Version
题目详情: This time let us consider the situation in the movie "Live and Let Die" in which James Bond, the worlds most famous spy, was captured by a group of drug dealers. He was sent to a small piece of land at the center of a lake f…...

线程同步条件变量
为何要线程同步 在线程互斥中外面解决了多线程访问共享资源所会造成的问题。 这篇文章主要是解决当多线程互斥后引发的新的问题:线程饥饿的问题。 什么是线程饥饿?互斥导致了多线程对临界区访问只能改变为串行,这样访问临界资源的代码只能…...

jeecgboot-vue3 查询区 label 文字居左实现
以系统管理中的系统角色界面为例 操作步骤 1. 通过路由或者工具找到当前代码所在的文件 src/views/system/role/index.vue 2. 找到 useListPage 调用,fromConfig 对象加入 labelWidth 和 rowProps 属性 formConfig: {labelWidth: 65, // 设置所有的label宽rowPr…...

CentOS系统环境搭建(五)——Centos7安装maven
centos系统环境搭建专栏🔗点击跳转 Centos7安装maven 下载压缩包 maven下载官网 解压 压缩包放置到/usr/local tar -xvf apache-maven-3.9.2-bin.tar.gz配置环境变量 vim /etc/profile在最下面追加 MAVEN_HOME/usr/local/apache-maven-3.9.2 export PATH${MAV…...

.eslintrc配置
ESLint 标准规则 /*** AlloyTeam ESLint 规则** 包含所有 ESLint 规则* 使用 babel-eslint 作为解析器** fixable 表示此配置支持 --fix* off 表示此配置被关闭了,并且后面说明了关闭的原因*/module.exports {parser: babel-eslint,parserOptions: {ecmaVersion: 2…...

LangChain手记 Models,Prompts and Parsers
整理并翻译自DeepLearning.AILangChain的官方课程:Models,Prompts and Parsers(源码可见) 模型,提示词和解析器(Models, Prompts and Parsers) 模型:大语言模型提示词:构建传递给模…...

Cannot resolve plugin ... maven插件和依赖无法下载解决方法
将 maven/conf/settings.xml 配置文件中的mirror修改成如下即可 <?xml version"1.0" encoding"UTF-8"?> <settings xmlns"http://maven.apache.org/SETTINGS/1.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"…...

【skynet】skynet 服务间通信
写在前面 skynet 服务之间有自己的一套高效通信 API 。本文给出简单的示例。 文章目录 写在前面准备工作编写代码运行结果 准备工作 首先要有一个编译好,而且工作正常的 skynet 。 编写代码 在 skynet/example 目录编写一个配置文件,两个代码文件。 …...

Flink的Standalone部署实战
在Flink是通用的框架,以混合和匹配的方式支持部署不同场景,而Standalone单机部署方便快速部署,记录本地部署过程,方便备查。 环境要求 1)JDK1.8及以上 2)flink-1.14.3 3)CentOS7 Flink相关信…...

open cv学习 (一)像素的操作
open cv 入门 像素的操作 demo1 import cv2 import os import numpy as np# 1、读取图像 # imread()方法# 设置图像的路径 Path "./img.png" # 设置读取颜色类型默认是1代表彩色图 0 代表灰度图 # 彩色图 flag 1 # 灰度图 #flag 0# 读取图像,返回值…...

基于C#的消息处理的应用程序 - 开源研究系列文章
今天讲讲基于C#里的基于消息处理的应用程序的一个例子。 我们知道,Windows操作系统的程序是基于消息处理的。也就是说,程序接收到消息代码定义,然后根据消息代码定义去处理对应的操作。前面有一个博文例子( C#程序的启动显示方案(无窗口进程发…...

C语言刷题指南(一)
📙作者简介: 清水加冰,目前大二在读,正在学习C/C、Python、操作系统、数据库等。 📘相关专栏:C语言初阶、C语言进阶、数据结构刷题训练营、有感兴趣的可以看一看。 欢迎点赞 👍 收藏 ⭐留言 &am…...

VMware虚拟机Ubuntu无法连接网络的解决方法
一、解决办法 网络适配器设置 终端依次执行下面命令即可 sudo nmcli networking off sudo nmcli networking onsudo service network-manager start #或者 sudo service NetworkManager start成功出现这个图标,即代表网络连接成功。...

基于CentOS 7 部署社区版Haproxy
HAProxy是法国开发者 威利塔罗(Willy Tarreau) 在2000年使用C语言开发的一个开源软件,是一款具 备高并发(一万以上)、高性能的TCP和HTTP负载均衡器,支持基于cookie的持久性,自动故障切换,支 持正则表达式及web状态统计。 目录 1…...

Git和GitHub
文章目录 1.Git介绍2. 常用命令3. Git分支操作4. Git团队协作机制5. GitHub操作6. IDEA集成Git7.IDEA操作GitHub8. Gitee 1.Git介绍 Git免费的开源的分布式版本控制系统,可以快速高效从小到大的各种项目 Git易于学习,占地面积小,性能快。它…...

spring入门基本介绍及注入方式---详细介绍
一,spring的简介 Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。 提供了许多功能强大且易于使用的特性,使得开发者能够更加轻松地构建可维护且可扩展的应用程序,简单来说: Spring使用基…...

神经网络基础-神经网络补充概念-24-随机初始化
由来 在神经网络的训练过程中,权重和偏差的初始值对模型的性能和训练过程的收敛速度都有影响。随机初始化是一种常用的权重和偏差初始值设置方法,它有助于打破对称性,避免网络陷入局部最优解。 概念 当所有权重和偏差都被设置为相同的初始…...

K8S之存储卷
K8S之存储卷 一、emptyDir emptyDir:可实现Pod中的容器之间共享目录数据,但emptyDir存储卷没有持久化数据的能力,存储卷会随着Pod生命周期结束而一起删除二、hostPath hostPath:将Node节点上的目录/文件挂载到Pod容器的指定目录…...

8月17日,每日信息差
1、专家称无需太过担心EG.5变异株 2、快手职级体系调整,职级序列由双轨变单轨 3、抖音、火山引擎、中国电影资料馆发起“经典香港电影修复计划”,一年内将100部香港电影修复至4K版本。本次修复工作由火山引擎提供技术支持,与中国电影资料馆…...

VBA技术资料MF44:VBA_把数据从剪贴板粘贴到Excel
【分享成果,随喜正能量】人皆知以食愈饥,莫知以学愈愚,生命中所有的不期而遇都是你努力的惊喜.人越纯粹,就越能感受到美。大江、大河、大海、大山、大自然,这些风景从来都不会受“属于谁”的污染,人人都感受到它们的美…...

nestjs:nginx反向代理服务器后如何获取请求的ip地址
问题: 如题 参考: nodejsnginx获取真实ip-腾讯云开发者社区-腾讯云 「转」从限流谈到伪造 IP nginx remote_addr 解决办法: 1.设置nginx 对于代理部分,对http header添加Host、X-Real-IP、X-Forwarded-For(最重要&…...

STM32 F103C8T6学习笔记7:双机无线串口通信
今日尝试配通俩个C8T6单片机之间的无线串口通信,文章提供原理,源码,测试效果图,测试工程下载: 目录 传输不规范问题: 串口通信资源: 单个串口资源理解: 单片机串口资源…...

开源数据库Mysql_DBA运维实战 (DDL语句)
DDL DDL语句 数据库定义语言:数据库、表、视图、索引、存储过程. 例如:CREATE DROP ALTER DDL库 定义库{ 创建业务数据库:CREAATE DATABASE ___数据库名___ ; 数据库名要求{ a.区分大小写 b.唯一性 c.不能使用关键字如 create select d.不能单独使用…...