Spring security 身份验证失败时引发异常

Spring security 身份验证失败时引发异常,spring-security,exception-handling,spring-boot,Spring Security,Exception Handling,Spring Boot,我在我的springboot应用程序中实现了一些基于令牌的身份验证。我有一个过滤器,在该过滤器中,我执行以下操作: @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest httpRequest = (HttpServletRequ

我在我的
springboot
应用程序中实现了一些基于令牌的身份验证。我有一个过滤器,在该过滤器中,我执行以下操作:

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    String authToken = httpRequest.getHeader("X-TOKEN-AUTH");
    String username = null;

    if (securityEnabled) {
       if (authToken != null) {

            try {
                username = userTokenService.validateToken(authToken);
                UserDetails userDetails = userDetailsService.loadUserByUsername(username);
                UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), null, userDetails.getAuthorities());
                auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
                SecurityContextHolder.getContext().setAuthentication(auth);

            } catch (AuthenticationException ae) {
                //TODO log something about signature exception
                log.warn(ae.getMessage());
            }
        }

    }

    chain.doFilter(request, response);
}
我还有一个自定义AuthFailureHandler:

@Component
public class AuthFailureHandler extends SimpleUrlAuthenticationFailureHandler {
    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        PrintWriter writer = response.getWriter();
        writer.write(exception.getMessage());
        writer.flush();
    }
}
我的代码
username=userTokenService.validateToken(authToken)引发
身份验证异常
AuthenticationException
是扩展
exception
的自定义异常。当我捕获到这个异常时,我仍然希望返回401,但我希望我的消息显示在当前由
Spring Security
以JSON形式发送回来的默认消息中:

{
    "timestamp": 1463408604943,
    "status": 401,
    "error": "Unauthorized",
    "message": "An Authentication object was not found in the SecurityContext",
    "path": "/api/brands/2"
}
例如,我想

{
    "timestamp": 1463408604943,
    "status": 401,
    "error": "Unauthorized",
    "message": "Invalid Token: Expired",
    "path": "/api/brands/2"
}

我不确定如何覆盖这种行为。

所以……我终于找到了答案。问题是过滤器在食物链中的位置更高,所以它们实际上不太涉及春天。当我在过滤器中抛出异常时,Spring不一定会捕获它。过滤器将抛出500并显示异常消息。要修复它,我只需在过滤器中捕获我的异常,然后使用适当的http状态调用
senderro

try {
  username = userTokenService.validateToken(authToken);
  UserDetails userDetails = userDetailsService.loadUserByUsername(username);
  UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), null, userDetails.getAuthorities());
  auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
  SecurityContextHolder.getContext().setAuthentication(auth);
  chain.doFilter(request, response);
  return;
} catch (Exception ex) {
  httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
  return;
}

catch
中的
return
语句是这样的:
chain.doFilter(请求、响应)doFilter
方法末尾的code>。

所以…我终于解决了这个问题。问题是过滤器在食物链中的位置更高,所以它们实际上不太涉及春天。当我在过滤器中抛出异常时,Spring不一定会捕获它。过滤器将抛出500并显示异常消息。要修复它,我只需在过滤器中捕获我的异常,然后使用适当的http状态调用
senderro

try {
  username = userTokenService.validateToken(authToken);
  UserDetails userDetails = userDetailsService.loadUserByUsername(username);
  UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(userDetails.getUsername(), null, userDetails.getAuthorities());
  auth.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
  SecurityContextHolder.getContext().setAuthentication(auth);
  chain.doFilter(request, response);
  return;
} catch (Exception ex) {
  httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED, ex.getMessage());
  return;
}

catch
中的
return
语句是这样的:
chain.doFilter(请求、响应)doFilter
方法末尾的code>。

AuthenticationException
是您的自定义异常或spring的
AuthenticationException
?它是我自己的自定义异常类此
AuthenticationException
是您的自定义异常或spring的
AuthenticationException
?它是我自己的自定义异常类