当第二个筛选器尝试写入响应流时,2个链接的AbstractAuthenticationProcessingFilter导



我有两个过滤器,Filter1Filter2,它们都扩展了AbstractAuthenticationProcessingFilterFilter1已经成功地完成了它的工作并将请求链接到Filter2。现在,当Filter2抛出AuthenticationException并由Filter2的onAuthenticationFailure方法处理时,响应将被写入到具有HttpStatus 403的响应流中,因此响应被提交。但在调用doFilter方法(在Filter1中)后,控件被链接回Filter1,并且它重定向到"/"url,这导致了302重定向状态,而不是我所期望的403重定向状态。有人知道如何在异常期间跳过过滤器链以避免重定向到"/"url吗?

它是spring-boot应用程序,两个过滤器都在ApplicationConfig.java中配置,并带有单独的ErrorHandlerErrorhandler1Errorhandler2FirstFilter已将身份验证状态设置为true,第二个筛选器抛出异常。但由于Response已经由链中第二个筛选器的Errorhandler2("AuthenticationFailureHandler")提交,但控制权仍然转到Filter1并重定向到"/"。

@Component
public class Filter2CustomErrorhandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
CustomError error = new CustomError();
response.setContentType("application/json;charset=UTF-8");
response.setStatus(403);
response.getWriter().write(convertObjectToJson(error));
}
private String convertObjectToJson(Object object) throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
}
}
public class Filter1 extends AbstractAuthenticationProcessingFilter {
public Filter1(RequestMatcher requiresAuthenticationRequestMatcher) {
super(requiresAuthenticationRequestMatcher);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
Authentication authentication = new CustomAuthenticationToken("some-principal-1", "some-credential-1");
authentication.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}
@Override
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
}   

public class Filter2 extends AbstractAuthenticationProcessingFilter {
public Filter2(RequestMatcher requiresAuthenticationRequestMatcher) {
super(requiresAuthenticationRequestMatcher);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
Authentication authentication = new CustomAuthenticationToken("some-principal-2", "some-credential-2");
authentication.setAuthenticated(true);
throw new SecurityAuthenticationException("some-exception-message", new CustomException());
//SecurityContextHolder.getContext().setAuthentication(authentication);
//return authentication;
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
super.successfulAuthentication(request, response, chain, authResult);
chain.doFilter(request, response);
}
@Override
public void setAuthenticationFailureHandler(AuthenticationFailureHandler failureHandler) {
super.setAuthenticationFailureHandler(failureHandler);
}
} 

我正在RestClient中等待HttpStatus 403。

解决方案:

  • 所以实现这一点的另一种方法是CCD_ 16和多个提供者。

  • 单个提供程序可以实现的重写支持方法特定的CCD_ 17类型(例如ExampleAuthInstance extends Authentication)。

  • 当您从类似的筛选器调用提供程序时CCD_ 19,支持ExampleAuthInstance的提供者,身份验证方法将调用该提供程序的。

  • AuthenticationException必须从过滤器本身抛出,而不是从提供者抛出。相反,提供者可以抛出具有所需HttpStatusCustomSecurityException,然后将其封装在AuthenticationException中并在过滤器级别抛出。然后将其委托给可能想要响应流的适当的预配置CCD_ 25。

最新更新