1 文章导读
Spring Security 是 Spring 家族中的一个安全管理框架,可以和Spring Boot项目很方便的集成。Spring Security框架的两大核心功能:认证和授权
认证: 验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户。简单的理解就是登陆操作,如果可以登录成功就说明您是本系统的用户,如不能登录就说明不是本系
统的用户!而且登录成功以后需要记录当前登录用户的信息!
授权:经过认证后判断当前用户是否有权限进行某个操作!
如上图所示就是展示了当前登录用户可以操作的权限:用户管理、角色管理、菜单管理等,并且针对角色管理可以进行新增、修改、删除、导出等权限。
而现在前后端分离开发成为了主流的开发方式,那么在前后端分离开发方式下如何使用Spring Security就是本文章需要重点研究的内容。
2 Spring Security认证功能
2.1 前端分离项目的认证流程
要想了解如果使用Spring Security进行认证,那么就需要先了解一下前后端分离项目中的认证流程,如下所示:
2.2 Spring Security原理初探
要想使用Spring Security框架来实现上述的认证操作,就必须先要了解一个Spring Security框架的工作流程。
2.2.1 过滤器链
Spring Security的原理其实就是一个过滤器链,内部包含了提供各种功能的过滤器。这里我们可以看看入门案例中的过滤器。
图中只展示了核心过滤器,其它的非核心过滤器并没有在图中展示。
UsernamePasswordAuthenticationFilter: 负责处理我们在登陆页面填写了用户名密码后的登陆请求。
ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationException 。
FilterSecurityInterceptor:负责权限校验的过滤器。
2.2.2 认证流程
Spring Security的认证流程大致如下所示:
概念速查:
Authentication接口: 它的实现类,表示当前访问系统的用户,封装了用户相关信息。
AuthenticationManager接口:定义了认证Authentication的方法
UserDetailsService接口:加载用户特定数据的核心接口。里面定义了一个根据用户名查询用户信息的方法。
UserDetails接口:提供核心用户信息。通过UserDetailsService根据用户名获取处理的用户信息要封装成UserDetails对象返回。然后将这些信息封装到Authentication对象中。
2.3 认证实现
在前后端分离项目中,前端请求的是我们自己定义的认证接口。因为在认证成功以后就需要针对当前用户生成token,Spring Security中提供的原始认证就无法实现了。在我们自定
义的认证接口中,需要调用Spring Security的API借助于Spring Security实现认证。
2.3.1 思路分析
认证:
1、自定义认证接口
① 调用ProviderManager的方法进行认证 如果认证通过生成jwt
② 把用户信息存入redis中
2、自定义UserDetailsService
① 在这个实现类中去查询数据库
校验:
1、定义Jwt认证过滤器
① 获取token
② 解析token获取其中的userid
③ 从redis中获取用户信息
④ 存入SecurityContextHolder
2.3.2 集成Redis
添加依赖
<!--redis依赖--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency>
添加redis配置
在application.yml文件中添加Redis的相关配置
spring:redis:host:127.0.0.1port:6379
2.3.3 集成Mybatis Plus
添加依赖
<!-- 引入mybatis plus的依赖 --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.3</version></dependency><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><!-- lombok依赖包 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency>
创建数据库表
CREATETABLE`sys_user` (
`id`BIGINT(20) NOTNULL AUTO_INCREMENT COMMENT'主键',
`user_name`VARCHAR(64) NOTNULLDEFAULT'NULL'COMMENT'用户名',
`nick_name`VARCHAR(64) NOTNULLDEFAULT'NULL'COMMENT'昵称',
`password`VARCHAR(64) NOTNULLDEFAULT'NULL'COMMENT'密码',
`status`CHAR(1) DEFAULT'0'COMMENT'账号状态(0正常 1停用)',
`email`VARCHAR(64) DEFAULTNULLCOMMENT'邮箱',
`phone_number`VARCHAR(32) DEFAULTNULLCOMMENT'手机号',
`sex`CHAR(1) DEFAULTNULLCOMMENT'用户性别(0男,1女,2未知)',
`avatar`VARCHAR(128) DEFAULTNULLCOMMENT'头像',
`user_type`CHAR(1) NOTNULLDEFAULT'1'COMMENT'用户类型(0管理员,1普通用户)',
`create_by`BIGINT(20) DEFAULTNULLCOMMENT'创建人的用户id',
`create_time` DATETIME DEFAULTNULLCOMMENT'创建时间',
`update_by`BIGINT(20) DEFAULTNULLCOMMENT'更新人',
`update_time` DATETIME DEFAULTNULLCOMMENT'更新时间',
`del_flag`INT(11) DEFAULT'0'COMMENT'删除标志(0代表未删除,1代表已删除)',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2DEFAULTCHARSET=utf8mb4 COMMENT='用户表'-- 插入数据insertinto security.sys_user (id, user_name, nick_name, password, status, email, phone_number, sex, avatar, user_type, create_by, create_time, update_by, update_time, del_flag) values (1501123580308578309, 'zhangsan', '张三', '1234', '0', 'hly@itcast.cn', '1312103105', '0', 'http://www.itcast.cn', '1', 1, '2022-03-08 09:12:06', 1, '2022-03-08 09:12:06', 0);
数据库相关配置
spring:
datasource:
url: jdbc:mysql://l