package com.alatus.config.filter; import com.alatus.constant.Constants; import com.alatus.model.TUser; import com.alatus.result.R; import com.alatus.service.RedisService; import com.alatus.util.JSONUtils; import com.alatus.util.JWTUtils; import com.alatus.util.ResponseUtils; import com.alatus.result.CodeEnum; import jakarta.annotation.Resource; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import java.util.concurrent.TimeUnit; @Component public class TokenVerifyFilter extends OncePerRequestFilter { @Resource private RedisService redisService; @Resource // springboot框架提供的线程池,ioc容器内已经存在 private ThreadPoolTaskExecutor threadPoolTaskExecutor; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (request.getRequestURI().equals(Constants.LOGIN_URI)) { //如果是登录请求,此时还没有生成jwt,那不需要对登录请求进行jwt验证 //验证jwt通过了 ,让Filter链继续执行,也就是继续执行下一个Filter filterChain.doFilter(request, response); } else { String token = request.getHeader(Constants.TOKEN_NAME); if(!StringUtils.hasText(token)){ // 没拿到token,将失败这个枚举传回去,解析并取出常量拼接 R result = R.FAIL(CodeEnum.TOKEN_IS_EMPTY); // 封装 String resultJSON = JSONUtils.toJSON(result); // 返回 ResponseUtils.write(response,resultJSON); return; } // 验证token有没有被篡改过,也是验证token合法性 if (!(JWTUtils.verifyJWT(token))){ // token不合法 R result = R.FAIL(CodeEnum.TOKEN_IS_NONE_MATCH); // 封装 String resultJSON = JSONUtils.toJSON(result); // 返回 ResponseUtils.write(response,resultJSON); return; } TUser tUser = JWTUtils.parseUserFromJWT(token); String redisToken = (String) redisService.getValue(Constants.REDIS_JWT_KEY + tUser.getId()); if(!StringUtils.hasText(redisToken)){ // 没有获取到内容说明token过期了 R fail = R.FAIL(CodeEnum.TOKEN_IS_EXPIRED); String json = JSONUtils.toJSON(fail); ResponseUtils.write(response,json); return; } if (!redisToken.equals(token)) { // 登陆失败token错误 R result = R.FAIL(CodeEnum.TOKEN_IS_ERROR); // 把R对象转为JSON String json = JSONUtils.toJSON(result); ResponseUtils.write(response,json); return; } // jwt验证通过了 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser,tUser.getLoginPwd(),tUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); // 刷新一下token // 做异步执行 // new Thread(new Runnable() { // @Override // public void run() { 这里刷新token即可 从请求头中获取 // String rememberMe = request.getHeader("rememberMe"); // if (!Boolean.parseBoolean(rememberMe)) { // redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS); // } // } // }).start(); // 最好使用线程池的方式去执行 // threadPoolTaskExecutor.execute(() -> { // 这里刷新token即可 // 从请求头中获取 // String rememberMe = null; // if(StringUtils.hasText(request.getHeader(Constants.REMEMBER_ME))){ // rememberMe = request.getHeader(Constants.REMEMBER_ME); // } // if (!Boolean.parseBoolean(rememberMe)) { // redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS); // } // }); // 验证jwt通过了,让filter链继续执行 // 经过实验,线程池有概率导致请求和我们的service走的线程不是同一个导致请求头里面获取这个rememberMe报错 // 还是不用线程为好,慢点就慢点吧 String rememberMe = null; if(StringUtils.hasText(request.getHeader(Constants.REMEMBER_ME))){ rememberMe = request.getHeader(Constants.REMEMBER_ME); } if (!Boolean.parseBoolean(rememberMe)) { redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS); } filterChain.doFilter(request,response); } } }
package com.alatus.config.filter; import com.alatus.constant.Constants; import com.alatus.model.TUser; import com.alatus.result.R; import com.alatus.service.RedisService; import com.alatus.util.JSONUtils; import com.alatus.util.JWTUtils; import com.alatus.util.ResponseUtils; import com.alatus.result.CodeEnum; import jakarta.annotation.Resource; import jakarta.servlet.FilterChain; import jakarta.servlet.ServletException; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.filter.OncePerRequestFilter; import java.io.IOException; import java.util.concurrent.TimeUnit; @Component public class TokenVerifyFilter extends OncePerRequestFilter { @Resource private RedisService redisService; @Resource // springboot框架提供的线程池,ioc容器内已经存在 private ThreadPoolTaskExecutor threadPoolTaskExecutor; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if (request.getRequestURI().equals(Constants.LOGIN_URI)) { //如果是登录请求,此时还没有生成jwt,那不需要对登录请求进行jwt验证 //验证jwt通过了 ,让Filter链继续执行,也就是继续执行下一个Filter filterChain.doFilter(request, response); } else { String token = request.getHeader(Constants.TOKEN_NAME); if(!StringUtils.hasText(token)){ // 没拿到token,将失败这个枚举传回去,解析并取出常量拼接 R result = R.FAIL(CodeEnum.TOKEN_IS_EMPTY); // 封装 String resultJSON = JSONUtils.toJSON(result); // 返回 ResponseUtils.write(response,resultJSON); return; } // 验证token有没有被篡改过,也是验证token合法性 if (!(JWTUtils.verifyJWT(token))){ // token不合法 R result = R.FAIL(CodeEnum.TOKEN_IS_NONE_MATCH); // 封装 String resultJSON = JSONUtils.toJSON(result); // 返回 ResponseUtils.write(response,resultJSON); return; } TUser tUser = JWTUtils.parseUserFromJWT(token); String redisToken = (String) redisService.getValue(Constants.REDIS_JWT_KEY + tUser.getId()); if(!StringUtils.hasText(redisToken)){ // 没有获取到内容说明token过期了 R fail = R.FAIL(CodeEnum.TOKEN_IS_EXPIRED); String json = JSONUtils.toJSON(fail); ResponseUtils.write(response,json); return; } if (!redisToken.equals(token)) { // 登陆失败token错误 R result = R.FAIL(CodeEnum.TOKEN_IS_ERROR); // 把R对象转为JSON String json = JSONUtils.toJSON(result); ResponseUtils.write(response,json); return; } // jwt验证通过了 UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser,tUser.getLoginPwd(),tUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); // 刷新一下token // 做异步执行 // new Thread(new Runnable() { // @Override // public void run() { 这里刷新token即可 从请求头中获取 // String rememberMe = request.getHeader("rememberMe"); // if (!Boolean.parseBoolean(rememberMe)) { // redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS); // } // } // }).start(); // 最好使用线程池的方式去执行 // threadPoolTaskExecutor.execute(() -> { // 这里刷新token即可 // 从请求头中获取 // String rememberMe = null; // if(StringUtils.hasText(request.getHeader(Constants.REMEMBER_ME))){ // rememberMe = request.getHeader(Constants.REMEMBER_ME); // } // if (!Boolean.parseBoolean(rememberMe)) { // redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS); // } // }); // 验证jwt通过了,让filter链继续执行 // 经过实验,线程池有概率导致请求和我们的service走的线程不是同一个导致请求头里面获取这个rememberMe报错 // 还是不用线程为好,慢点就慢点吧 String rememberMe = null; if(StringUtils.hasText(request.getHeader(Constants.REMEMBER_ME))){ rememberMe = request.getHeader(Constants.REMEMBER_ME); } if (!Boolean.parseBoolean(rememberMe)) { redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS); } filterChain.doFilter(request,response); } } }