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