实现拦截器
有图片可知,在上篇文章我们重写了UserDetailsManager,现在我们来进行之后的操作
在UserDetailsManager中我们可以调动数据库去进行一个账号密码的校验
之后我们这样设置拦截器进行一个token获取存储在usernamePasswordAuthenticationFilter这一层中,
有,则存储在SecurityContextHolder.getContext()中供接下来的调用,没有就放行
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {@Autowiredprivate RedisCache redisCache;@Overrideprotected void doFilterInternal(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, FilterChain filterChain) throws ServletException, IOException {String token = httpServletRequest.getHeader("token");if(!StringUtils.hasText(token)){filterChain.doFilter(httpServletRequest,httpServletResponse);return;}String userId="";try {Claims claims = JwtUtil.parseJWT(token);userId = claims.getSubject();} catch (Exception e) {throw new RuntimeException(e);}LoginUser cacheObject = redisCache.getCacheObject("login:" + userId);if(Objects.nonNull(cacheObject)){UsernamePasswordAuthenticationToken token1=new UsernamePasswordAuthenticationToken(cacheObject,null,null);SecurityContextHolder.getContext().setAuthentication(token1);}filterChain.doFilter(httpServletRequest,httpServletResponse);}
}
启用拦截器
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;@Beanpublic BCryptPasswordEncoder passwordEncoder(){return new BCryptPasswordEncoder();}@Overrideprotected void configure(HttpSecurity http) throws Exception {http//关闭csrf.csrf().disable()//不通过Session获取SecurityContext.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()// 对于登录接口 允许匿名访问.antMatchers("/user/login").anonymous()// 除上面外的所有请求全部需要鉴权认证.anyRequest().authenticated();http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);}@Bean@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}
}```,
注意:
1.不用去想着token没有的情况,由以上逻辑可以看出来,我们将token获取后会存入 SecurityContextHolder中,之后的内置拦截器会检测是否有token,没有就报错,不用自己设置监测
2.其次,一定要注意,在拦截器中放生login接口
3.登录前UsernamePasswordAuthenticationToken存的是账号密码,登录后转入 SecurityContextHolder时,存的是对象