我有两个过滤器,Filter1
和Filter2
,它们都扩展了AbstractAuthenticationProcessingFilter
。Filter1
已经成功地完成了它的工作并将请求链接到Filter2
。现在,当Filter2
抛出AuthenticationException
并由Filter2的onAuthenticationFailure
方法处理时,响应将被写入到具有HttpStatus 403的响应流中,因此响应被提交。但在调用doFilter
方法(在Filter1中)后,控件被链接回Filter1
,并且它重定向到"/"url,这导致了302重定向状态,而不是我所期望的403重定向状态。有人知道如何在异常期间跳过过滤器链以避免重定向到"/"url吗?
它是spring-boot应用程序,两个过滤器都在ApplicationConfig.java中配置,并带有单独的ErrorHandlerErrorhandler1
和Errorhandler2
。FirstFilter
已将身份验证状态设置为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
必须从过滤器本身抛出,而不是从提供者抛出。相反,提供者可以抛出具有所需HttpStatus
的CustomSecurityException
,然后将其封装在AuthenticationException
中并在过滤器级别抛出。然后将其委托给可能想要响应流的适当的预配置CCD_ 25。