【问题标题】:How to handle spring security InternalAuthenticationServiceException thrown in Spring ProviderManager如何处理 Spring ProviderManager 中抛出的 Spring Security InternalAuthenticationServiceException
【发布时间】:2023-04-04 03:08:01
【问题描述】:

ProviderManager 在 DaoAuthenticationProvider.class 中检索用户时抛出 InternalAuthenticationServiceException.class,

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

我想处理这个异常并将我的自定义响应返回给客户端。

我不想通过编写自定义 ProviderManager 来处理这个问题。

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

但我无法捕捉到像 InternalAuthenticationServiceException.class 这样的安全异常。

我没有选择将 ErrorController 与 /error 路径一起使用,它会破坏其他流程。

【问题讨论】:

  • 您使用的 Web 框架是什么?弹簧控制器还是泽西岛?
  • @shazin 我正在使用 Spring Boot 和 Spring Security 2.0.8
  • 我也面临这个问题.. 解决方案是什么?

标签: java spring spring-security spring-boot


【解决方案1】:

您可以编写一个带有@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.
                    } 
                });
    }

【讨论】:

  • ControllerAdvice 在安全引发异常时没有被调用。我正在使用@EnableAuthorizationServer,所以我的服务中没有任何明确的控制器。
  • AuthorizationServerEndpointsConfigurer 类型中的方法 exceptionTranslator(WebResponseExceptionTranslator) 不适用于参数 (( e) -> {})
【解决方案2】:

首先你需要实现你自己的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);
    ...
    }

仅此而已。 :)

【讨论】:

    【解决方案3】:

    我已经通过在我的过滤器中覆盖 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());
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-07
      • 2019-06-28
      • 2015-07-03
      • 2017-07-11
      • 2011-01-24
      • 2015-03-21
      • 1970-01-01
      • 2017-05-28
      相关资源
      最近更新 更多