问题
ProviderManager is throwing InternalAuthenticationServiceException.class while retrieving users in DaoAuthenticationProvider.class,
loadedUser = this.getUserDetailsService().loadUserByUsername(username);
I want to handle this exception and return my custom response to the client.
I don't want to handle this by writing custom ProviderManager.
For all other OAuth exceptions i am able to handle the exceptions using Custom WebResponseExceptionTranslator.
But I am unable to catch security exceptions like InternalAuthenticationServiceException.class.
I don't have option to use ErrorController with the /error path, it is breaking other flows.
回答1:
You can write a class which is annotated with @ControllerAdvice
and have a @ExceptionHandler(value=InternalAuthenticationServiceException.class)
.
Ex:-
@ControllerAdvice
public class ExceptionHandler {
@ExceptionHandler(InternalAuthenticationServiceException.class)
public ResponseEntity<String> handleInternalAuthenticationServiceException(InternalAuthenticationServiceException e) {
ResponseEntity<String> response = new ResponseEntity<String>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
return response;
}
}
UPDATE
If you don't have controllers and using @EnableAuthorizationServer
then you need to extend from AuthorizationServerConfigurerAdapter
and override configure(AuthorizationServerEndpointsConfigurer endpoints)
as below. You can use AuthorizationServerEndpointsConfigurer.exceptionTranslator
to handle your InternalAuthenticationServiceException
.
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
// other endpoints
.exceptionTranslator(e -> {
if (e instanceof InternalAuthenticationServiceException) {
InternalAuthenticationServiceException internalAuthenticationServiceException = (InternalAuthenticationServiceException) e;
// return a ResponseEntity or throw a custom Exception.
}
});
}
回答2:
First you need to implements your own AuthenticationEntryPoint the name is not really autoexplicative...
For example if you need to return always status code 200 (only for learning purpose, please don´t do it in real world...)
@Component("myOwnAuthenticationEntryPoint")
public class MyOwnAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, org.springframework.security.core.AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_OK, "Unauthorized");
}
Then in your WebSecurityConfig you need to set it as your authentication exception handler entry point.
...
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
...
@Autowired
MyOwnAuthenticationEntryPoint myOwnAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.exceptionHandling().authenticationEntryPoint(myOwnAuthenticationEntryPoint);
...
}
Thats all. :)
回答3:
I've solved that problem by override unsuccessfulAuthentication method in my filter and send an error response to the client with the desired HTTP status code. In my case, I also created my custom exception (RecordNotFoundException) that is thrown from my service.
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
AuthenticationException failed) throws IOException, ServletException {
if (failed.getCause() instanceof RecordNotFoundException) {
response.sendError((HttpServletResponse.SC_NOT_FOUND), failed.getMessage());
}
}
来源:https://stackoverflow.com/questions/39789408/how-to-handle-spring-security-internalauthenticationserviceexception-thrown-in-s