【问题标题】:Set Cookie before Spring Security Filter Chain在 Spring Security Filter Chain 之前设置 Cookie
【发布时间】:2025-12-11 08:50:01
【问题描述】:

我想设置一个referrer cookie,因为我需要排除一些页面(例如错误、登录、注销等),以便能够在登录后重定向到最后调用但未排除的页面:

public class CookieReferrerFilter extends OncePerRequestFilter {
    public static final String REFERRER_COOKIE_NAME = "REFERRER";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (!isReferrerExcluded(request)) {
            Cookie sessionCookie = new Cookie(REFERRER_COOKIE_NAME, request.getRequestURI());
            sessionCookie.setPath(!"".equals(request.getContextPath()) ? request.getContextPath() : "/");
            sessionCookie.setSecure(false);
            sessionCookie.setMaxAge(-1);

            response.addCookie(sessionCookie);
        }

        filterChain.doFilter(request, response);
    }

    private boolean isReferrerExcluded(HttpServletRequest request) {
        for (String pattern : EXCLUDED_REFERRER) {
            if (new AntPathRequestMatcher(pattern).matches(request)) {
                return true;
            }
        }

        return false;
    }
}

但是 Spring Security Filter Chain 在 CookieReferrerFilter 之前被触发。 因此,调用安全页面将立即将我重定向到登录页面,而无需之前调用 CookieReferrerFilter.doFilterInternal 并且没有设置 cookie。

有一个类配置 webbapp(设置配置类、映射、过滤器),它扩展了 AbstractAnnotationConfigDispatcherServletInitializer

public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[] { ApplicationContextConfig.class };
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return null;
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] { "/" };
    }

    @Override
    protected Filter[] getServletFilters() {
        CookieReferrerFilter cookieReferrerFilter = new CookieReferrerFilter();

        CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
        characterEncodingFilter.setEncoding("UTF-8");
        characterEncodingFilter.setForceEncoding(true);

        return new Filter[] { cookieReferrerFilter, characterEncodingFilter };
    }
}

还有一个只是扩展AbstractSecurityWebApplicationInitializer:

public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
}

【问题讨论】:

标签: java spring spring-security


【解决方案1】:

假设您正在使用 Spring Security 的基于 Java 的配置,您可以让您的过滤器由 Spring 管理,并将其添加到 Spring Security 过滤器链的开头(很大程度上来自 HttpSecurity javadoc 中的示例(见下文链接):

 @Configuration
 @EnableWebSecurity
 public class HttpSecurityConfig extends WebSecurityConfigurerAdapter {

     @Autowired  CookieReferrerFilter cookieFilter;

     @Autowired CharacterEncodingFilter encodingFilter;

     @Override
     protected void configure(HttpSecurity http) throws Exception {
         http
             .addFilterBefore(cookieFilter, ChannelProcessingFilter.class)
             .addFilterBefore(encodingFilter, ChannelProcessingFilter.class)
               //your configuration follows here
                ; 
      }
   }

详情请参阅http://docs.spring.io/autorepo/docs/spring-security/current/apidocs/org/springframework/security/config/annotation/web/builders/HttpSecurity.html#addFilter(javax.servlet.Filter)

【讨论】: