授权与认证之jwt(四)创建OAuth2Filter类
- 互联网
- 2025-09-16 20:57:02

接上篇讲到授权与认证之jwt(三)刷新令牌该如何设计 这篇文章中要注意
注意事项: 因为在OAuth2 Filter类中要读写 ThreadLocal中的数据,所以OAuth:2 Filter类 必须要设置成多例的,否则ThreadLocal将无法使用。
一、在配置文件中,添加)WT需要用到的密钥、过期时间和缓存过期时间。
emos: jwt: #密钥 secret: abc123456 #令牌过期时间(天) expire: 5 #令牌缓存时间(天) cache-expire: 10二、创建OAuth2Filter类
@Component @Scope("prototype") public class OAuth2Filter extends AuthenticatingFilter { @Autowired private ThreadLocalToken threadLocalToken; @Value("${emos.jwt.cache-expire}") private int cacheExpire; @Autowired private JwtUtil jwtUtil; //用于往redis中存取数据 @Autowired private RedisTemplate redisTemplate; /** * 拦截请求后,用于把令牌字符串封装成令牌对象 */ @Override protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception { HttpServletRequest req=(HttpServletRequest)request; String token = getRequestToken(req); if (StrUtil.isBlank(token)) { return null; } return new OAuth2Token(token); } /** *判断哪种请求可以被shiro处理 */ @Override protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue){ HttpServletRequest req = (HttpServletRequest)request; //ajax提交application/json数据的时候,会先发出Option请求 //这里要放行Option请求,不需要shiro处理 if (req.getMethod().equals(RequestMethod.OPTIONS.name())) { return true; } //除了Options请求之外,所以请求都要被shiro处理 return false; } /** * 该方法用于处理所有应该被shiro处理的请求 */ @Override protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { HttpServletRequest req = (HttpServletRequest)servletRequest; HttpServletResponse resp = (HttpServletResponse)servletResponse; //允许跨域请求 resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); resp.setHeader("Access-Control-Allow-Credentials", "true"); resp.setContentType("text/html;charset=utf-8"); threadLocalToken.clear(); String token = getRequestToken(req); if (StrUtil.isBlank(token)) { resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); resp.getWriter().print("无效令牌"); return false; } //验证token是否内容有效,验证是否过期 try { jwtUtil.verifyToken(token); }catch (TokenExpiredException e){ //查redis有没有该令牌 if (redisTemplate.hasKey(token)) { //有数据,需要删掉缓存的老令牌,重新生成新令牌 redisTemplate.delete(token); int userId=jwtUtil.getUserId(token); //创建新token token=jwtUtil.createToken(userId); //把token存到redis中 redisTemplate.opsForValue().set(token,userId+"",cacheExpire, TimeUnit.DAYS); //把token存到threadLocal中 threadLocalToken.setToken(token); }else { //客户端和redis中令牌都过期,需要用户重新登录 resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); resp.getWriter().print("令牌已过期"); return false; } }catch (JWTDecodeException e){ resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); resp.getWriter().print("无效令牌"); return false; } //此时令牌没问题 boolean b = executeLogin(req, resp); return b; } @Override protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { HttpServletRequest req = (HttpServletRequest)servletRequest; HttpServletResponse resp = (HttpServletResponse)servletResponse; //允许跨域请求 resp.setHeader("Access-Control-Allow-Origin", req.getHeader("Origin")); resp.setHeader("Access-Control-Allow-Credentials", "true"); resp.setContentType("text/html;charset=utf-8"); resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED); try { resp.getWriter().print(e.getMessage()); } catch (IOException ex) { throw new RuntimeException(ex); } return false; } @Override public void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException { super.doFilterInternal(request, response, chain); } /** * 获取token方法 */ private String getRequestToken(HttpServletRequest req){ String token = req.getHeader("token"); if (StrUtil.isBlank(token)) { //从请求体中获取数据 token=req.getParameter("token"); } return token; } }授权与认证之jwt(四)创建OAuth2Filter类由讯客互联互联网栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“授权与认证之jwt(四)创建OAuth2Filter类”