**
* 对非登陆请求过滤,验证token
*
* 1:判断请求头里是否携带token。请求时候怎么在请求头里携带jwt?怎么拿token里的jwt?
* 没带,交给后面过滤器处理
* 如果有,走第2步
*
* 2:判断token的合法性。即decode是否能解开。
* 不合法:交给后面过滤器处理
* 合法:走到第3步
*
* 3:判断 redis token 是否过期
* 过期:交给后面过滤器处理
* 没过期:走到第4步
*
* 4:判断请求头里的 token 是否等于 redis里的 存的 token,即是否是当前用户的token
* 不一样:交给后面过滤器处理
* 一样:给 token 续期
@Component
public class JWTFilter extends OncePerRequestFilter {
@Autowired
private RedisTemplate<String,Object>redisTemplate;
@Autowired
SecurityService securityService;
@SneakyThrows
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
//第一步
String token = request.getHeader("token");
if(token==null){
filterChain.doFilter(request,response);
return;
}
//第二步
if(!JWTUtil.decode(token)){
filterChain.doFilter(request,response);
return;
}
Map userInfo = JWTUtil.getUserInfo(token);
String userId = String.valueOf(userInfo.get("userId"));
//第三步
String redisToken = (String) redisTemplate.opsForValue().get("token:"+userId);
if(redisToken==null){
filterChain.doFilter(request,response);
return;
}
//第四步
if(!token.equals(redisToken)){
filterChain.doFilter(request,response);
return;
}
redisTemplate.opsForValue().set("token:"+userId,token,30, TimeUnit.MINUTES);
filterChain.doFilter(request,response);
}
}
还没完,接下来还有一步。
因为security框架默认是通过session方式记录登陆状态,可能会对jwt产生干扰,所以 我们要禁掉session 并用唯一的jwt方式登陆。 在security.config类加一行
//前后端项目中要禁用掉session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
在禁掉session后 没有了登陆凭证 ,所以当对方经过了一系列校验之后,我们要在security容器中,手动放入登陆凭证。
//第五步 放入登陆凭证
/**
* UsernamePasswordAuthenticationToken是一种登陆凭证
*/
UserDetails userDetails = securityService.loadUserByUsername((String)userInfo.get("accont"));
UsernamePasswordAuthenticationToken upa =
new UsernamePasswordAuthenticationToken( userDetails.getUsername(),
userDetails.getPassword(),
userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(upa);
filterChain.doFilter(request,response);
然后再去security.config类注册
http.addFilterAfter(jwtFilter, UsernamePasswordAuthenticationFilter.class);