You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebSecurityConfigurerAdapter中配置CORP头特定路径例外

解决Spring Security特定路径移除Cross-Origin-Resource-Policy头的问题

问题场景

我们基于Spring Security的WebSecurityConfigurerAdapter配置安全头,核心代码中为所有请求添加了Cross-Origin-Resource-Policy: SAME_ORIGIN头,确保非同源请求无法加载资源,符合预期。但现在需要为/public_resources/**路径设置例外:保留该路径的其他所有安全头,仅移除Cross-Origin-Resource-Policy头,且网站域名是动态生成的,无法硬编码。

之前尝试的两种方法均无效:

  • 在configure方法末尾添加antMatches配置StaticHeadersWriter,意外覆盖了其他路径的安全头;
  • 创建独立的WebSecurityConfigurerAdapter子类配置例外,未生效。

使用环境:spring-framework.version 5.3.39;spring-boot-starter-parent 2.7.18;JDK 21。

有效解决方案

方案一:自定义HeaderWriter(推荐,无需重复配置安全头)

通过扩展CrossOriginResourcePolicyHeaderWriter,根据请求路径判断是否写入Cross-Origin-Resource-Policy头,避免重复配置所有安全头。

  1. 实现自定义HeaderWriter:
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;
import org.springframework.web.util.AntPathMatcher;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class PathExcludingCORPHeaderWriter extends CrossOriginResourcePolicyHeaderWriter {
    private final AntPathMatcher pathMatcher = new AntPathMatcher();
    private final String excludedPathPattern;

    public PathExcludingCORPHeaderWriter(CrossOriginResourcePolicy policy, String excludedPathPattern) {
        super(policy);
        this.excludedPathPattern = excludedPathPattern;
    }

    @Override
    public void writeHeaders(HttpServletRequest request, HttpServletResponse response) {
        // 仅当请求路径不匹配排除规则时,才写入CORP头
        if (!pathMatcher.match(excludedPathPattern, request.getRequestURI())) {
            super.writeHeaders(request, response);
        }
    }
}
  1. 修改原SecurityConfig配置:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 保留原有其他安全头配置
        http.headers()
                // 示例:其他安全头配置(根据你的实际需求调整)
                .contentTypeOptions()
                .and()
                .xssProtection()
                .and()
                .frameOptions()
                // 替换原有的crossOriginResourcePolicy配置为自定义HeaderWriter
                .and()
                .addHeaderWriter(new PathExcludingCORPHeaderWriter(
                        CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.SAME_ORIGIN,
                        "/public_resources/**"
                ))
                .and()
                // 其他HttpSecurity配置...
                .authorizeRequests()
                .anyRequest().authenticated();
    }
}

方案二:多HttpSecurity配置(需同步安全头配置)

创建两个优先级不同的WebSecurityConfigurerAdapter子类,分别处理公共资源路径和全局路径,确保公共资源路径的配置先被匹配。

  1. 公共资源路径配置(高优先级):
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;

@Configuration
@Order(1) // 优先级高于全局配置,确保先匹配
public class PublicResourcesSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .requestMatchers()
                .antMatchers("/public_resources/**")
                .and()
                .headers()
                // 同步全局配置中的所有安全头,除了禁用CORP头
                .contentTypeOptions()
                .and()
                .xssProtection()
                .and()
                .frameOptions()
                // 禁用CORP头的自动添加
                .and()
                .crossOriginResourcePolicy().disable()
                .and()
                // 其他安全头配置(与全局保持一致)
                .and()
                // 公共资源路径的授权规则(根据实际需求调整)
                .authorizeRequests()
                .antMatchers("/public_resources/**").permitAll();
    }
}
  1. 全局路径配置:
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.header.writers.CrossOriginResourcePolicyHeaderWriter;

@Configuration
@EnableWebSecurity
public class GlobalSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .headers()
                // 配置所有安全头,包括CORP
                .contentTypeOptions()
                .and()
                .xssProtection()
                .and()
                .frameOptions()
                .and()
                .crossOriginResourcePolicy()
                .policy(CrossOriginResourcePolicyHeaderWriter.CrossOriginResourcePolicy.SAME_ORIGIN)
                .and()
                // 其他安全头配置
                .and()
                // 全局授权规则
                .authorizeRequests()
                .anyRequest().authenticated();
    }
}

原方法无效原因说明

  1. StaticHeadersWriter覆盖问题:StaticHeadersWriter是设置固定的响应头集合,会直接替换原有头配置,导致其他安全头丢失,而非仅移除特定头。
  2. 独立配置未生效:未给独立配置类添加@Order注解,导致全局配置先被匹配,覆盖了例外规则;或者例外配置中未同步全局的安全头配置,导致公共资源路径丢失其他安全头。

内容的提问来源于stack exchange,提问作者Kevin Cruijssen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 11:57:19