首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >自定义异常未通过spring boot中的通知控件传递

自定义异常未通过spring boot中的通知控件传递
EN

Stack Overflow用户
提问于 2021-09-28 12:54:51
回答 2查看 134关注 0票数 0

TokenExpiredException异常应该在控制器通知中处理,但返回一个常见的、未处理的错误。

JWTValidarFilter:

代码语言:javascript
运行
复制
public class JWTValidarFilter extends BasicAuthenticationFilter{

private static final String HEADER_ATRIBUTO = "Authorization";

private static final String ATRIBUTO_PREFIXO = "Bearer ";

public JWTValidarFilter(AuthenticationManager authenticationManager) {
    super(authenticationManager);
}

@Override
protected void doFilterInternal(HttpServletRequest request, 
        HttpServletResponse response, FilterChain chain)
        throws IOException, ServletException {
    
    String atributo = request.getHeader(HEADER_ATRIBUTO);
            
    if(atributo == null) {
        chain.doFilter(request, response);
        return;
    }
    
    if(!atributo.startsWith(ATRIBUTO_PREFIXO)) {
        chain.doFilter(request, response);
        return;
    }
    
    String token = atributo.replace(ATRIBUTO_PREFIXO, "");
    
    UsernamePasswordAuthenticationToken authenticationToken = getAuthenticationToken(token);
    SecurityContextHolder.getContext().setAuthentication(authenticationToken);
    chain.doFilter(request, response);
    
    
}

private UsernamePasswordAuthenticationToken getAuthenticationToken(String token) {
    
    
    try {
        String usuario = JWT.require(Algorithm.HMAC512(JWTAutenticarFilter.TOKEN_SENHA))
                .build()
                .verify(token)
                .getSubject();
        if(usuario == null) {
            return null;
        }
        
        return new UsernamePasswordAuthenticationToken(usuario, null, new ArrayList<>());

    } catch (TokenExpiredException e) {
        throw new TokenExpiredException("Token expirado!");
    }
    
}

}

CustomizeResponseEntityExceptionHandler:

代码语言:javascript
运行
复制
@ControllerAdvice
@RestController
public class CustomizeResponseEntityExceptionHandler extends ResponseEntityExceptionHandler{

    @ExceptionHandler(Exception.class)
    public final ResponseEntity<ExceptionResponse> handleAllExcepetions(Exception ex, WebRequest request){
        ExceptionResponse exceptionResponse = 
                new ExceptionResponse(new Date(), ex.getMessage(), request.getDescription(false));
        
        return new ResponseEntity<>(exceptionResponse, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    @ExceptionHandler(InvalidJwtAuthenticationException.class)
    public final ResponseEntity<ExceptionResponse> invalidJwtAuthenticationException(Exception ex, WebRequest request){
        ExceptionResponse exceptionResponse = 
                new ExceptionResponse(new Date(), 
                        ex.getMessage(), 
                        request.getDescription(false));
        
        return new ResponseEntity<>(exceptionResponse, HttpStatus.BAD_REQUEST);
    }

    @ExceptionHandler(TokenExpiredException.class)
    public final ResponseEntity<ExceptionResponse> TokenExpiredException(TokenExpiredException ex, WebRequest request){
        ExceptionResponse exceptionResponse = 
                new ExceptionResponse(new Date(), 
                        ex.getMessage(), 
                        request.getDescription(true));
        
        return new ResponseEntity<>(exceptionResponse, HttpStatus.UNAUTHORIZED);
    }

    
    @ExceptionHandler(HttpClientErrorException.class)
    public ResponseEntity<String> handleException(HttpClientErrorException ex) throws HttpClientErrorException {
        System.out.println("*******Exception Occured: *************" + ex);
        return ResponseEntity
                .status(HttpStatus.UNAUTHORIZED)
                .body(" -----DD------ Exception: " + ex.getLocalizedMessage());
    }
}
EN

回答 2

Stack Overflow用户

发布于 2021-09-30 23:31:14

尝试构建自定义AuthenticationFailureHandler,如下所示:

代码语言:javascript
运行
复制
public class CustomAuthenticationFailureHandler 
  implements AuthenticationFailureHandler {
 
    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
       AuthenticationException exception) throws IOException, ServletException {

        Throwable cause = exception.getCause();
        ExceptionResponse exceptionResponse = null;

        if (cause instanceOf InvalidJwtAuthenticationException) {
          response.setStatus(HttpStatus.BAD_REQUEST.value());
          exceptionResponse = new ExceptionResponse(new Date(), 
                cause.getMessage(), 
                request.getDescription(false));
        } else if (cause instanceOf TokenExpiredException) {
          response.setStatus(HttpStatus.UNAUTHORIZED.value());
          exceptionResponse = new ExceptionResponse(new Date(), 
                ex.getMessage(), 
                request.getDescription(true));
        } else {
          // additional logic here
        }

        response.getOutputStream().println(objectMapper.writeValueAsString(exceptionResponse));
    }
}

然后你需要在一个@Configuration类中注册它:

代码语言:javascript
运行
复制
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
    return new CustomAuthenticationFailureHandler();
}
票数 0
EN

Stack Overflow用户

发布于 2021-10-01 04:18:14

您不能使用控制器通知来捕获身份验证异常(至少不是那么简单:-)。身份验证异常发生在整个Spring异常处理程序初始化之前。下面是关于如何解决相关问题的类似讨论:

Spring MVC (or Spring Boot). Custom JSON response for security related exceptions like 401 Unauthorized or 403 Forbidden)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69362148

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档