framework: springboot+IDEA+spring security oauth2
background: user login to get token, username or password authentication failure, the execution of onAuthenticationFailure method, has returned the normal error code and error message, but the console still throws an exception, the error message is as follows.
2021-09-12 07:16:25.490 WARN 964 — [nio-8090-exec-1] d.c.h.CustomAuthenticationFailureHandler : Authentication failed, the return message is: {“code”:1100, “info”: “User does not exist.”}
2021-09-12 07:16:25.500 ERROR 964 — [nio-8090-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [/api/sso] threw exceptionjava.lang.IllegalStateException: Cannot call sendError() after the response has been committed
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:456) ~[tomcat-embed-core-9.0.52.jar:9.0.52]
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:120) ~[tomcat-embed-core-9.0.52.jar:4.0.FR]
at javax.servlet.http.HttpServletResponseWrapper.sendError(HttpServletResponseWrapper.java:120) ~[tomcat-embed-core-9.0.52.jar:4.0.FR]
at org.springframework.security.web.util.OnCommittedResponseWrapper.sendError(OnCommittedResponseWrapper.java:126) ~[spring-security-web-5.5.2.jar:5.5.2]
at org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler.onAuthenticationFailure(SimpleUrlAuthenticationFailureHandler.java:86) ~[spring-security-web-5.5.2.jar:5.5.2]
at com.datong.liran.datongssoserver.config.handle.CustomAuthenticationFailureHandler.onAuthenticationFailure(CustomAuthenticationFailureHandler.java:39) ~[classes/:na]
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.unsuccessfulAuthentication(AbstractAuthenticationProcessingFilter.java:342) ~[spring-security-web-5.5.2.jar:5.5.2]
The error code and error message have been returned normally, but the console still reports an error, not the result I want, so what should I do? The custom exception handling code looks like this.
@Component("CustomAuthenticationFailureHandler")
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.reset();
// PrintWriter printWriter = httpServletResponse.getWriter();
OutputStream out = response.getOutputStream();
response.setContentType("application/json;charset=UTF-8");
Result result = Result.error(1100,exception.getMessage(),null);
String rspBodyStr = JSONObject.toJSONString(result);
logger.warn("The authentication fails and the return message is:"+rspBodyStr);
out.write(rspBodyStr.getBytes(StandardCharsets.UTF_8));
out.close();
super.onAuthenticationFailure(request,response,exception);
}
}
Cannot call senderror() after the response has been committed.
Analysis: according to the error log, it is preliminarily judged that it should be repeated submission or repeated return, but only response is involved here, so you can only go to the parent class (onauthenticationfailure). Open it and have a look. The code is as follows.
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
if (this.defaultFailureUrl == null) {
if (this.logger.isTraceEnabled()) {
this.logger.trace("Sending 401 Unauthorized error since no failure URL is set");
} else {
this.logger.debug("Sending 401 Unauthorized error");
}
response.sendError(HttpStatus.UNAUTHORIZED.value(), HttpStatus.UNAUTHORIZED.getReasonPhrase());
} else {
this.saveException(request, exception);
if (this.forwardToDestination) {
this.logger.debug("Forwarding to " + this.defaultFailureUrl);
request.getRequestDispatcher(this.defaultFailureUrl).forward(request, response);
} else {
this.redirectStrategy.sendRedirect(request, response, this.defaultFailureUrl);
}
}
}
Obviously, when the defaultfailureurl is null, the senderror () method is executed, which should be the same as the previous setting, and this method also reports an error in the error log. Since the error code and error information I want have been returned, I simply do not call the parent method. After a try, sure enough, the console no longer reports an error and returns normally.
Solution: no longer call the parent class method, and annotate super.onauthenticationfailure (request, response, exception); sentence.
OK, get it done and start sharing the joy of success.
Read More:
- [Solved] Cannot call sendError() after the response has been committed
- [Redirect anomaly] Cannot call sendRedirect() after the response has been committed
- Cannot call sendRedirect() after the response has been committed
- [Solved] java.lang.IllegalStateException: Cannot call sendRedirect() after the response has been committed
- [Solved] springsecurity custom exceptions: Error: Parse Error: Response overflow
- [Solved] HttpPost Call https Interface error: PKIX path building failed
- How to Download File via Response (Example Code)
- Using java to call Jython, the error URI is not hierarchical
- [Solved] Java.lang.IllegalStateException: getReader() has already been called for this request
- [Solved] Spring integrates canal to call feign error: pool-1-thread-1
- Microservice call exceptions: error feign.RetryableException: Read timed out executing POST http://xxx…….
- Gitee Idea Push Error: Invocation failed Server returned invalid Response. java.lang.RuntimeException
- [Solved] Java.lang.BootstrapMethodError: call site initialization exception
- [Solved] Rocketmq remote connection error: sendDefaultimpl call timeout
- [Solved] Feign Call Port Error: HttpMessageNotReadableException:JSON parse error:Illegal character ((CTRL-CHAR, code 31)
- Feign call Error: duplicate name [How to Solve]
- [Solved] port (127.0.0.1:64444): java.net.SocketException “Interrupted function call: accept failed“
- [Solved] Error response from daemon: driver failed programming external connectivity on endpoint mymysql
- [Solved] docker Error response from daemon driver failed programming external connectivity on endpoint lamp
- [Solved] Openfegn Remote Call Error: java.lang.NullPointerException: null