I'm using spring security web 5.0.9 and tomcat 8. ExceptionTranslationFilter throw ServletException "Unable to handle the Spring Security Exception because the response is already committed." I dig into the source code and find the root cause. I'm not sure whether it is a bug for spring security.
I throw the UsernameNotFoundException in AuthenticationUserDetailsService.loadUserDetails
SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure catch the exception and then call
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException exception)
throws IOException, ServletException {
if (defaultFailureUrl == null) {
logger.debug("No failure URL set, sending 401 Unauthorized error");
response.sendError(HttpStatus.UNAUTHORIZED.value(),
HttpStatus.UNAUTHORIZED.getReasonPhrase());
}
the sendError will set response committed to true, see ResponseFacade.java:
public void sendError(int sc, String msg)
throws IOException {
...
response.setAppCommitted(true);
...
}
- Then ExceptionTranslationFilter catch it and check the response commit status, found it's true and then throw the exception
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
...
if (response.isCommitted()) {
throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", ex);
...
}
- nobody catch the ServletException and the application try to find the /web_framework/error_page/405.html
I find the spring security code is changed in this bug fix https://github.com/spring-projects/spring-security/issues/5273.
How to deal with the ServletException and return the valid 401 response, but not web_framework/error_page/405.html
SimpleUrlAuthenticationFailureHandler
is invoked, then theExceptionTranslationFilter
is not also invoked since there is no further response handling required. – jzheaux