package com.example.springsecurity3.hndler;
import com.example.springsecurity3.service.impl.SecurityService;
import com.example.springsecurity3.utils.JWTUtils;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.TimeUnit;
/**
* security整合jwt用的过滤器
* 1:判断除登录请求外,是否携带jwt,如果没有携带,放行不处理(过滤连上的其他过滤器会处理)
* 2:判断携带的jwt是否合法(),不合法,放行不处理
* 3:拿redis的jwt和携带的jwt做对比
* 一:redis的jwt已过期,放掉不处理
* 二:把双方的jwt的值进行对比
*/
@Component
public class JWTFilter extends OncePerRequestFilter {
@Autowired(required = false)
private RedisTemplate<String,String> redisTemplate;
@Autowired
private SecurityService securityService;
//帮我们处理异常
@SneakyThrows
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
//在请求头拿到jwt
String jwt = request.getHeader("jwt");
if (jwt==null){
//放给security其他处理器处理此方法,该方法不做处理
filterChain.doFilter(request,response);
return;
}
//如果jwt不合法,则放行,给其他过滤器处理
if (!JWTUtils.getDecrypt(jwt)){
filterChain.doFilter(request,response);
return;
}
//获取jwt的用户信息(通过jwt工具类的获取载荷方法拿去)
Map account = JWTUtils.getAccount(jwt);
//获取username
String username = (String) account.get("username");
//拿到redis的jwt
String redisJwt = redisTemplate.opsForValue().get("jwt:" + username);
//如果redis中的jwt过期怎不处理放行
if (redisJwt==null){
filterChain.doFilter(request,response);
return;
}
//判断jwt是否和redis中的jwt相等
if (!jwt.equals(redisJwt)){
filterChain.doFilter(request,response);
return;
}
//给redis的jwt续期
redisTemplate.opsForValue().set("jwt:"+username,
jwt,15, TimeUnit.MINUTES);
//生成()凭证(通过SecurityService类中的loadUserByUsername方法获取用户名,密码,和权限)或者重新在usersDao中心方法从数据库中获取
UserDetails userDetails = securityService.loadUserByUsername(username);
//
UsernamePasswordAuthenticationToken upa=new UsernamePasswordAuthenticationToken(
//通过SecurityService类中的方法获取(用户名,密码,权限)
userDetails.getUsername(),userDetails.getPassword(),userDetails.getAuthorities());
//往security容器中注入凭证(用户名,密码,权限)
SecurityContextHolder.getContext().setAuthentication(upa);
//本方法功能执行完毕,交给下一个过滤器
filterChain.doFilter(request,response);
}
}