流程:
UsernamePasswordAuthenticationFilter:负责处理我们在登录页面填写了用户名密码后的登录请求
ExceptionTranslationFilter:处理过滤器链中抛出的任何AccessDeniedException(授权异常)和AuthenticationException(认证异常)
FilterSecurityInterceptor:负责权限校验的过滤器
![](https://img-blog.csdnimg.cn/direct/24c51f9a7c62455ebb2c29a4d130c889.png)
认证授权流程
思路分析:
登录
1.自定义登录接口
- 调用ProviderManager的authenticate方法进行认证 如果认证通过生成jwt
- 把用户信息存入redis中
2.自定义UserDetailsService
在这个实现类中去查询数据库
校验:
1.定义Jwt认证过滤器
2.获取token
3.解析token获取其中的userid
4.从redis中获取用户信息
5.存入SecurityContextHolder
![](https://img-blog.csdnimg.cn/img_convert/d861803118711aacf1547e0ca20a39e2.png)
授权基本流程
在SpringSecurity中,会使用默认的FilterSecurityInceptor来进行权限校验。
在FilterSecurityInceptor中会从SecurityContextHolder获取其中的Authentication,然后获取其中的权限信息。当前用户是否有访问当前资源所需的权限。
所以我们在项目中只需要把当前登陆用户的权限信息也存入Authentication.
然后设置我们的所需资源需要的权限即可
2.在方法上指定这个需要的权限
![](https://img-blog.csdnimg.cn/img_convert/e658057abfb22597a73ba0a385387472.png)
3.在实体类中定义权限属性,查询后封装到该属性中
@Data
@NoArgsConstructor
public class LoginUser implements UserDetails {
private User user;
private List<String>permissions;
@JSONField(serialize = false)// redis为了安全,不会序列化这个对象
private List<SimpleGrantedAuthority> authorities ;
public LoginUser(User user, List<String> permissions) {
this.user = user;
this.permissions = permissions;
}
// 该方法返回一个身份认证对象
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
// 把permissions中String类型的权限信息封装成SimpleGrantedAuthority对象
if (authorities!=null){
return authorities;
}
authorities=permissions.stream().map(SimpleGrantedAuthority::new).collect(Collectors.toList());
return authorities;
}
4.在UserDetail中封装权限信息
![](https://img-blog.csdnimg.cn/img_convert/e3d2e50d2b8cb852a5f4ad43dc192784.png)
5.在过滤器中进行身份认证
// 4.存入SecurityContextHolder
// 使用有三个参数的构造器,第三个参数可以设置为已认证状态
UsernamePasswordAuthenticationToken authToken =
new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authToken);