0. 简介
- Spring Security和Shiro比较。中大型的项目都是使用SpringSecurity做安全框架,小项目使用Shiro比较多,因为它比Spring Security上手更加简单
- 认证与授权:
- 认证:验证当前访问系统的是不是本系统的用户,并确认具体是那个用户
- 授权:经过认证后判断当前用户是否具有权限进行某个操作
1. 快速入门
1.1 准备工作
- 创建SpringBoot项目,导入相关的依赖
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.0</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
1.2 引入Spring Security
- 导入Spring Security依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
- 导入Security依赖之后,再次访问后端请求时会默认打开一个登录页面
- 此处默认的用户名(Username)是
user
,密码(Password)会在后台打印出来一长串字符,登录后就能够正常访问请求 - Security默认的登出网址
/logout
2. 认证
2.1 登录校验流程
2.2 原理
SpringSecurity原理是一个过滤器链,内部包含了提供各种功能的过滤器。
UsernamePasswordAuthenticationFilter
:负责处理我们在登录页面填写的用户名密码后的登录请求ExceptionTranslationFilter
:处理过滤器链中抛出的任何AccessDeniedException和AuthenticationExceptionFilterSecurityInterceptor
:负责权限校验的过滤器
认证流程详解:
- 提交用户名密码
- 封装Authentication对象,只有用户名密码,没有权限
- 调用authenticate方法进行认证
- 调用DaoAuthenticationProvider的authenticate方法进行认证
- 调用loadUserByUsername方法查询用户
- 根据用户名查询用户及对应的权限信息
- 把对应的用户信息包括权限信息封装成UserDetail对象
- 通过PasswordEncoder对比UserDetails中的密码和Authentication的密码是否一致
- 如果正确就把UserDetails中的权限信息设置到Authentication对象中
- 如果上一步返回了Authentication对象就是用SecurityContextHolder.getContext().setAuthentication()方法存储该对象,其他过滤器会通过SecurityContextHolder获取当前用户信息
2.3 解决问题
- 登录:
- 自定义登录接口,调用ProviderManager的方法进行认证,认证通过把用户信息存入redis
- 自定义UserDetailsService,在这个实现类中查询数据库
- 校验:
- 定义jwt认证过滤器,获取token,解析token,获取其中的userid,从redis获取用户信息
- 将用户信息存入SecurityContextHolder