我正在使用 Spring MVC 的 @ControllerAdvice
和 @ExceptionHandler
来处理 REST Api 的所有异常。它适用于 web mvc 控制器抛出的异常,但不适用于 spring security 自定义过滤器抛出的异常,因为它们在调用控制器方法之前运行。
我有一个自定义的 spring 安全过滤器,它执行基于令牌的身份验证:
public class AegisAuthenticationFilter extends GenericFilterBean {
...
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
try {
...
} catch(AuthenticationException authenticationException) {
SecurityContextHolder.clearContext();
authenticationEntryPoint.commence(request, response, authenticationException);
}
}
}
使用此自定义入口点:
@Component("restAuthenticationEntryPoint")
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint{
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authenticationException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authenticationException.getMessage());
}
}
并使用此类全局处理异常:
@ControllerAdvice
public class RestEntityResponseExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({ InvalidTokenException.class, AuthenticationException.class })
@ResponseStatus(value = HttpStatus.UNAUTHORIZED)
@ResponseBody
public RestError handleAuthenticationException(Exception ex) {
int errorCode = AegisErrorCode.GenericAuthenticationError;
if(ex instanceof AegisException) {
errorCode = ((AegisException)ex).getCode();
}
RestError re = new RestError(
HttpStatus.UNAUTHORIZED,
errorCode,
"...",
ex.getMessage());
return re;
}
}
我需要做的是返回一个详细的 JSON 正文,即使对于 spring security AuthenticationException。有没有办法让 spring security AuthenticationEntryPoint 和 spring mvc @ExceptionHandler 一起工作?
我正在使用 spring security 3.1.4 和 spring mvc 3.2.4。
原文由 Nicola 发布,翻译遵循 CC BY-SA 4.0 许可协议
好的,我尝试按照建议从 AuthenticationEntryPoint 自己编写 json 并且它有效。
只是为了测试,我通过删除 response.sendError 更改了 AutenticationEntryPoint
通过这种方式,即使您使用的是 Spring Security AuthenticationEntryPoint,您也可以发送自定义 json 数据以及 401 未授权。
显然,您不会像我出于测试目的那样构建 json,但您会序列化一些类实例。
在 Spring Boot 中,您应该将其添加到 SecurityConfiguration 文件的 http.authenticationEntryPoint() 部分。