不想努力的程序员 2024-04-20 19:27 采纳率: 52.5%
浏览 10
已结题

GlobalExceptionHandler 无法捕获Spring Security AuthenticationException 异常

在使用GlobalExceptionHandler 进行全局捕获异常时,自定义了CustomAuthenticationEntryPoint去捕获springSecurity的异常,在GlobalExceptionHandler 也进行了捕获,但是CustomAuthenticationEntryPoint是捕获到了,但是GlobalExceptionHandler 无法捕获,这个怎么处理,具体代码如下
CustomAuthenticationEntryPoint类

package com.xjc.common.handler;


@Component
public class CustomAuthenticationEntryPoint implements AuthenticationEntryPoint {
    @Override
    public void commence(HttpServletRequest request, HttpServletResponse response,
                         AuthenticationException authException) throws IOException, ServletException {

        System.out.println(authException.getMessage());
        response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "认证失败,请重新登录");
    }
}

GlobalExceptionHandler 类如下

package com.xjc.common.handler;


@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    @ExceptionHandler(value = Exception.class)
    public Response handleGeneralException(Exception ex, WebRequest request) {
        // 在这里可以记录异常信息到日志中
         log.error("发生异常: " +ex.getMessage() , ex);



        // 返回带有错误信息的响应
        return ResponseCode.customizeResponse( true,HttpStatus.INTERNAL_SERVER_ERROR.value(),ex.getMessage());
    }

    @ExceptionHandler(value = AccessDeniedException.class)
    public Response handleAccessDeniedException(AccessDeniedException ex, WebRequest request) {
        // 处理AccessDeniedException的逻辑
        log.error(ex.getMessage());
        // ...
        return ResponseCode.invalidHeaderTokenResponse(ex.getMessage());
    }

    @ExceptionHandler(value = AuthenticationException.class)
    public Response handleAuthenticationException(AuthenticationException ex, WebRequest request) {
        // 处理AuthenticationException的逻辑
        log.error(ex.getMessage());

        return ResponseCode.invalidHeaderTokenResponse(ex.getMessage());
    }


}


Exception 和AuthenticationException都无法进行捕获,在jswt过滤器中是下面这么写的


   if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            LoginUserVO loginUserVO = (LoginUserVO) loginService.loadUserByUsername(username);
            boolean isTokenValid = false;
            //校验token准确性和是否过期,此处可以自定义校验,可以使用jwt自带的校验也可以通过数据库和redis等共同判断
//            String userInfo= (String) stringRedisTemplate.opsForValue().get(StrUtil.format(OauthTestApplication.REDIS_TOKEN_KEY,jwt));
//            if(StrUtil.isNotBlank(userInfo))isTokenValid=true;
            User cacheObject = redisUntil.getCacheObject("login:" + username);
            if(!Objects.isNull(cacheObject)) {
                isTokenValid=true;
            }
            if(!isTokenValid){
                throw new IOException("请重新登录");
            }
            if (loginUserVO != null && jwtService.isTokenValid(authHeader, loginUserVO) && isTokenValid) {
                /**
                 * 封装成用户的凭证,传入用户实体类和用户的权限集合,spring security会自动去判断是否拥有权限
                 */
                UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
                        loginUserVO,
                        null,
                        loginUserVO.getAuthorities()
                );
                /**
                 * 在 Spring Security 中,当用户进行认证时,会先通过 AuthenticationFilter 进行请求过滤,
                 * 然后调用 AuthenticationManager 进行认证。在认证过程中,Spring Security 会自动创建一个
                 * Authentication 对象,其中包含了认证请求的相关信息。如果你需要自定义 Authentication
                 * 对象的详细信息,就可以使用 WebAuthenticationDetailsSource 来创建 WebAuthenticationDetails 对象。
                 */
                authToken.setDetails(
                        new WebAuthenticationDetailsSource().buildDetails(req)
                );
                SecurityContextHolder.getContext().setAuthentication(authToken);
            }
        }

throw new IOException("请重新登录");报错后CustomAuthenticationEntryPoint是没有问题的,但是GlobalExceptionHandler 无法进行捕获,这个如何解决

  • 写回答

4条回答 默认 最新

  • 流华追梦 Java领域新星创作者 2024-04-21 13:49
    关注

    GlobalExceptionHandler 的 @ExceptionHandler 注解需要捕获的异常类型必须与抛出的异常类型一致。而 AuthenticationException 是 Security 中的一种认证异常,而 IOException 则是 Java 中的异常类型,两者不一致,导致 GlobalExceptionHandler 无法捕获 AuthenticationException 异常。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 5月2日
  • 已采纳回答 4月24日
  • 创建了问题 4月20日

悬赏问题

  • ¥15 elmos eeprom的读写问题
  • ¥15 使用Java milo连接Kepserver服务端报错?
  • ¥15 用ADS设计一款的射频功率放大器
  • ¥15 怎么求交点连线的理论解?
  • ¥20 软件开发方法学习来了
  • ¥15 微信小程序商城如何实现多商户收款 平台分润抽成
  • ¥15 HC32L176调试了一个通过TIMER5+DMA驱动WS2812B
  • ¥15 cocos的js代码调用wx.createUseInfoButton问题!
  • ¥15 关于自相关函数法和周期图法实现对随机信号的功率谱估计的matlab程序运行的问题,请各位专家解答!
  • ¥15 Python程序,深度学习,有偿私