繁体   English   中英

Spring Security:如何返回503服务不可用?

[英]Spring Security: How to Return 503 Service Unavailable?

我有一个使用Spring Security进行身份验证的RESTful Web服务。 我已经在我的应用程序中注册了一个自定义AuthenticationProvider ,该应用程序将其authenticate()业务逻辑委托给远程服务,该服务可能不可用。 当远程服务不可用时,我希望呼叫能够*返回503 Service Unavailable

Spring Security可以按预期处理403 Forbidden ,但是我想将503逻辑添加到某个地方。 AuthenticationProvider接口可以引发运行时AuthenticationException ,但是它及其后代将由ProviderManager处理。

这是我的WebSecurityConfigurer:

// how do I hook this into 'http'???
@Autowired
private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

protected void configure(HttpSecurity http) throws Exception {
  http
    .authenticationProvider(myAuthenticationProvider)
    .httpBasic()
    .and()
    .exceptionHandling()
        .authenticationEntryPoint(myAuthenticationEntryPoint)
        .accessDeniedHandler(myAccessDeniedHandler)
    .and()
    .sessionManagement()
    .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    .authorizeRequests()
    ...

给定我具有自定义AuthenticationProvider ,如何配置HttpSecurity以返回所需的503

*-诚然,这是一个极端的情况。

为您的Web服务认证注册一个AbstractAuthenticationProcessingFilter ,然后从那里尝试认证。 您可以在同一过滤器类中配置故障处理程序。

 public class AjaxLoginProcessingFilter extends AbstractAuthenticationProcessingFilter { private static Logger logger = LoggerFactory.getLogger(AjaxLoginProcessingFilter.class); private final AuthenticationSuccessHandler successHandler; private final AuthenticationFailureHandler failureHandler; private final ObjectMapper objectMapper; public AjaxLoginProcessingFilter(String defaultProcessUrl, AuthenticationSuccessHandler successHandler, AuthenticationFailureHandler failureHandler, ObjectMapper mapper) { super(defaultProcessUrl); this.successHandler = successHandler; this.failureHandler = failureHandler; this.objectMapper = mapper; } @Override public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { if (!HttpMethod.POST.name().equals(request.getMethod()) || !WebUtil.isAjax(request)) { if(logger.isDebugEnabled()) { logger.debug("Authentication method not supported. Request method: " + request.getMethod()); } throw new AuthMethodNotSupportedException("Authentication method not supported"); } LoginRequest loginRequest = objectMapper.readValue(request.getReader(), LoginRequest.class); if (StringUtils.isBlank(loginRequest.getUsername()) || StringUtils.isBlank(loginRequest.getPassword())) { throw new AuthenticationServiceException("Username or Password not provided"); } UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()); return this.getAuthenticationManager().authenticate(token); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { successHandler.onAuthenticationSuccess(request, response, authResult); } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { SecurityContextHolder.clearContext(); failureHandler.onAuthenticationFailure(request, response, failed); } 

}

LoginRequest.java

@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
        AuthenticationException e) throws IOException, ServletException {

    response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value());

 }

}

在身份验证提供程序中使身份验证失败,并实现AuthenticationFailureHandler,然后更改响应状态。

 @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { response.setStatus(HttpStatus.SERVICE_UNAVAILABLE.value()); } 

您可以指定何时要在故障处理程序中抛出哪个状态。

我能够通过使用2个自定义组件来解决它:

  • MyUnavailableException (扩展了AuthenticationException
  • Custom503AuthenticationEntryPoint
public class Custom503AuthenticationEntryPoint implements AuthenticationEntryPoint {

    public void commence(HttpServletRequest request, HttpServletResponse response,
      AuthenticationException ex) throws IOException, ServletException {
        if (ex instanceof MyUnavailableException) {
            response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value(), HttpStatus.SERVICE_UNAVAILABLE.getReasonPhrase());
        }
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM