参考自:spring-security 9. 异常处理_哔哩哔哩_bilibili
一、问题分析:
由于JwtTokenFilter在Controller之前,Controller层的异常捕获,是无法捕获到还没有请求到Controller时发生的异常的,所以自定义的全局异常捕获对Filter无法生效。
二、问题解决
首先在配置类中添加过滤器Filter
http.addFilterAfter(jwtAuthenticationTokenFilter, ExceptionTranslationFilter.class);
然后通过response和ObjectMapper返回Json格式的数据
@Resource private ObjectMapper objectMapper; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestURI = request.getRequestURI(); /** * 登录接口直接放行 */ if ("/login".equals(requestURI)) { filterChain.doFilter(request, response); return; } //不是登录接口,需要获取token并对token进行验证 //获取请求头中的token String token = request.getHeader("token"); if (!StringUtils.hasText(token)) { filterChain.doFilter(request, response); return; } log.info("token:{}", token); String userId = null; Claims claims = null; try { claims = jwtUtils.parseJWT(token); userId = claims.getSubject(); } catch (ExpiredJwtException | MalformedJwtException e) { response.setContentType("application/json;charset=UTF-8"); log.error(e.getMessage()); String s = objectMapper.writeValueAsString(Result.fail(404, e.getMessage())); response.getWriter().write(s); return; } //根据userId从redis中获取用户信息,如果没有该用户就代表该用户没有登录过 SecurityUser securityUser = (SecurityUser) redisTemplate.opsForValue().get("login" + userId); if (Objects.isNull(securityUser)) { response.setContentType("application/json;charset=UTF-8"); response.setStatus(403); logger.error("用户未登录"); String s = objectMapper.writeValueAsString(Result.fail(403, "用户未登录")); response.getWriter().write(s); return; } User user = securityUser.getUser(); log.info("成功获取到用户信息:{}", user); //将用户信息存放在SecurityContextHolder.getContext(),后面的过滤器就可以获得用户信息了。 UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user, null, null); SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken); filterChain.doFilter(request, response); }