【问题标题】:Onboarding filter in Spring Boot and Spring SecuritySpring Boot 和 Spring Security 中的入职过滤器
【发布时间】:2021-12-06 18:57:15
【问题描述】:

我正在尝试创建一个过滤器,以便将登录的用户重定向到入职页面,以防他们之前没有完成该过程。

这是我目前的过滤器:

@Component
@Order(110)
public class OnboardingFilter implements Filter {

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {

    // cast the request and response to HTTP
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    HttpServletResponse httpResponse = (HttpServletResponse) response;
    HttpSession session = httpRequest.getSession(false);

    SecurityContextImpl securityContext = (SecurityContextImpl) session.getAttribute("SPRING_SECURITY_CONTEXT");

    // if there's a logged user
    if (securityContext != null) {
      UserPrincipal principal = (UserPrincipal) securityContext.getAuthentication().getPrincipal();
        
      if (!principal.hasOnboarded()) {
        httpResponse.sendRedirect("/onboarding");
      }
    }

    // continue with the filter chain
    chain.doFilter(httpRequest, httpResponse);
  }

我为@Order 尝试了不同的值,但在每种情况下,http 响应都会生成可下载的内容,而不是显示实际请求的 URL 或发送重定向。有什么想法吗?

我遇到了这个异常:

Caused by: java.lang.IllegalStateException: Committed
    at org.eclipse.jetty.server.HttpChannel.resetBuffer(HttpChannel.java:917)
HttpChannel.java:917
    at org.eclipse.jetty.server.HttpOutput.resetBuffer(HttpOutput.java:1423)
HttpOutput.java:1423
    at org.eclipse.jetty.server.Response.resetBuffer(Response.java:1182)
Response.java:1182
    at org.eclipse.jetty.server.Response.sendRedirect(Response.java:534)
Response.java:534
    at org.eclipse.jetty.server.Response.sendRedirect(Response.java:543)
Response.java:543
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
    at org.springframework.security.web.firewall.FirewalledResponse.sendRedirect(FirewalledResponse.java:43)
FirewalledResponse.java:43
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
    at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
    at org.springframework.security.web.util.OnCommittedResponseWrapper.sendRedirect(OnCommittedResponseWrapper.java:135)
OnCommittedResponseWrapper.java:135
    at javax.servlet.http.HttpServletResponseWrapper.sendRedirect(HttpServletResponseWrapper.java:130)
HttpServletResponseWrapper.java:130
    at org.springframework.web.servlet.view.RedirectView.sendRedirect(RedirectView.java:627)
RedirectView.java:627
    at org.springframework.web.servlet.view.RedirectView.renderMergedOutputModel(RedirectView.java:314)
RedirectView.java:314
    at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:316)
AbstractView.java:316
    at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1373)
DispatcherServlet.java:1373
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1118)
DispatcherServlet.java:1118
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1057)
DispatcherServlet.java:1057
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
DispatcherServlet.java:943
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
FrameworkServlet.java:1006
    ... 94 common frames omitted

【问题讨论】:

    标签: spring spring-boot spring-security


    【解决方案1】:

    添加return 怎么样:

    httpResponse.sendRedirect("/onboarding");
    return;
    

    否则,您将继续使用过滤器链:

    chain.doFilter(httpRequest, httpResponse);
    

    不能 100% 确定这是否已经解决了您的问题,但也可能是一个问题。

    【讨论】:

      【解决方案2】:

      我最终通过实现 Spring 上下文感知 GenericFilterBean 解决了这个问题,如下所示:

      public class OnboardingFilter extends GenericFilterBean {
      
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
      
          HttpServletRequest httpRequest = (HttpServletRequest) request;
          HttpServletResponse httpResponse = (HttpServletResponse) response;
      
          if (SecurityContextHolder.getContext().getAuthentication() != null) {
            // some business logic
            httpResponse.sendRedirect("/onboarding");
          }
          else {
            chain.doFilter(httpRequest, httpResponse);
          }
        }
      }
      

      不要忘记将其添加到安全过滤器链中:

      @Override
      protected void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(new OnboardingFilter(), UsernamePasswordAuthenticationFilter.class)...
      

      【讨论】:

        猜你喜欢
        • 2018-01-15
        • 2015-10-19
        • 2019-10-01
        • 2015-10-13
        • 1970-01-01
        • 2020-11-04
        • 2019-07-16
        • 2015-06-09
        • 1970-01-01
        相关资源
        最近更新 更多