spring security 的jwt认证以及原理解析

白净垃圾桶 2020-05-15

1.我们需要建立一个token的生产解析管理器,用于生成token,获取Authentication,验证token格式,以及从请求中获取token;
2.因为我们使用token进行权限控制等,所以我们需要重写一个基于token认证的过滤器,截取请求中的token首先对其进行一个redis查询存在后并对其解析(解密-需要正常获取没有抛出异常)获取信息后,将其转化成Authentication设置到SecurityContextHolder.getContext()上下文中;
3.将此过滤器配置到spring securit的过滤器链中,并将此过滤器设置到UsernamePasswordAuthenticationFilter之前;
4.需要实现userDetailsService,并将权限信息设置到UserDetails,重写loadUserByUsername方法
5.将内容配置到继承于WebSecurityConfigurerAdapter的配置类中去,并设置相应的一些过滤器如跨域,如token过滤器,未取得凭证或未取得授权的拦截器,也可以自定义去实现注解基于不需要权限认证的配置项

6.其中UsernamePasswordAuthenticationFilter中进行校验的是通过loadUserByUsername生成一个UserDetails与传入的UsernamePasswordAuthenticationToken进行校对

7.AuthenticationManager作为身份认证的核心接口,当自定义登录的时候我们需要委托给他的实现类ProviderManager进行身份认证,其中ProviderManager中含有AuthenticationProvider列表,会依次轮询里面AuthenticationProvider,当所构造的Authentication(如:UsernamePasswordAuthentication)被支持后会调用authenticate方法,如UsernamePasswordAuthentication调用的就是DaoAuthenticationProvider中的authenticate方法:
retrieveUser(...): 调用子类 DaoAuthenticationProvider 的 retrieveUser()方法获取 UserDetails
preAuthenticationChecks.check(user): 对从上面获取的UserDetails进行预检查,即判断用户是否锁定,是否可用以及用户是否过期
additionalAuthenticationChecks(user,authentication): 对UserDetails附加的检查,对传入的Authentication与获取的UserDetails进行密码匹配
postAuthenticationChecks.check(user): 对UserDetails进行后检查,即检查UserDetails的密码是否过期
createSuccessAuthentication(principalToReturn, authentication, user): 上面所有检查成功后,利用传入的Authentication 和获取的UserDetails生成一个成功验证的Authentication

这个方法实际上是调用DaoAuthenticationProvider的additionalAuthenticationChecks方法,内部调用加密解密器进行密码匹配,如果匹配失败,则抛出一个 BadCredentialsException异常
最后通过createSuccessAuthentication(..)方法生成一个成功认证的 Authentication,简单说就是组合获取的UserDetails和传入的Authentication,得到一个完全填充的Authentication。
该Authentication最终一步一步向上返回,到AbstractAuthenticationProcessingFilter过滤器中,将其设置到 SecurityContextHolder。

8.自定义一个TokenFilter,将其设置在UsernamePasswordAuthenticationFilter之前,则会进行过滤器链的轮询,当TokenFilter能够正确的设置SercurityHolder的安全上下文,将其传递给下一个过滤器即UsernamePasswordAuthenticationFilter,(在此之前会判断此请求是否是匹配的需要身份验证的请求,不是则不执行下面描述的验证逻辑)但在该过滤器中需要验证login的Post方法并且需要携带username与password,所以此验证失败则直接返回,不再执行身份验证

9.最后才是真正的验证权限逻辑

相关推荐