[英]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.