如何处理Spring ProviderManager中抛出的Spring Security InternalAuthenticationServiceException异常

5

在 DaoAuthenticationProvider.class 中检索用户时,ProviderManager 抛出了 InternalAuthenticationServiceException.class 异常。

 loadedUser = this.getUserDetailsService().loadUserByUsername(username);

我希望能处理这个异常并向客户端返回我的自定义响应。

我不想通过编写定制的ProviderManager来处理此问题。

对于所有其他OAuth异常,我可以使用自定义的WebResponseExceptionTranslator来处理异常。

但是我无法捕获安全性异常,例如InternalAuthenticationServiceException.class。

我没有使用/error路径的ErrorController选项,因为这会破坏其他流程。


你在Web开发中使用的框架是什么?Spring Controllers还是Jersey? - shazin
@shazin 我正在使用 Spring Boot 和 Spring Security 2.0.8。 - Harish
我也遇到了这个问题..解决方案是什么? - Collin
3个回答

4
您可以编写一个使用@ControllerAdvice注释的类,并具有@ExceptionHandler(value=InternalAuthenticationServiceException.class)

例如:

@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;
    }

}

更新

如果你没有控制器,并且使用了@EnableAuthorizationServer,那么你需要继承AuthorizationServerConfigurerAdapter并按以下方式重写configure(AuthorizationServerEndpointsConfigurer endpoints)。你可以使用AuthorizationServerEndpointsConfigurer.exceptionTranslator来处理你的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.
                    } 
                });
    }

3
当安全性抛出异常时,ControllerAdvice没有被调用。我正在使用@EnableAuthorizationServer,因此在我的服务中没有明确的控制器。 - Harish
类型AuthorizationServerEndpointsConfigurer中的方法exceptionTranslator(WebResponseExceptionTranslator<OAuth2Exception>)不适用于参数((<no type> e) -> {})。 - Newsonic
即使在一个类中(使用Controller Advice注释)为InternalAuthenticationServiceException实现了异常处理程序,该异常仍未被捕获,应用程序仍然会抛出内部服务器错误以及基本异常。这里有处理程序被绕过的可能性吗? - Iqbal

3
首先,您需要实现自己的AuthenticationEntryPoint,名称并非十分具有自解性...
例如,如果您需要始终返回状态码200(仅供学习目的,请勿在真实环境中这样做...)
@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");
    } 

然后在您的WebSecurityConfig中,您需要将其设置为身份验证异常处理程序入口点。
...

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    ...

    @Autowired
    MyOwnAuthenticationEntryPoint myOwnAuthenticationEntryPoint;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.exceptionHandling().authenticationEntryPoint(myOwnAuthenticationEntryPoint);
    ...
    }

这是所有的内容。 :)

0

我通过在我的过滤器中重写unsuccessfulAuthentication方法并向客户端发送具有所需HTTP状态代码的错误响应来解决了这个问题。在我的情况下,我还创建了自定义异常(RecordNotFoundException),该异常会从我的服务中抛出。

@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());
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接