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

Spring Security如何配置指定页面允许任意站点iframe嵌入

Spring Security 5.3.x 按页面维度放开iframe嵌入限制实现方案

关于<frame-options>标签ref属性的说明

你查到的ref属性仅在policy="ALLOW-FROM"模式下生效,引用的Bean需要实现org.springframework.security.web.header.writers.frameoptions.AllowFromStrategy接口,接口定义如下:

public interface AllowFromStrategy {
    /**
     *  返回值为X-Frame-Options头ALLOW-FROM指令后拼接的允许来源域名
     *  返回null时将不输出X-Frame-Options头
     */
    String getAllowFromValue(HttpServletRequest request);
}

注意:X-Frame-Options: ALLOW-FROM 域名是非标准指令,当前主流Chrome、Edge、Safari浏览器均已废弃对该语法的支持,无法实现「允许任意第三方域名嵌入」的需求,不推荐使用该方案。

推荐实现方案(兼容所有浏览器)

核心思路是禁用默认的全局frame-options配置,通过请求匹配器对指定路径单独控制安全头输出:默认路径保持SAMEORIGIN策略,需要放开的路径不输出X-Frame-Options头,可搭配CSP指令做现代浏览器兼容。

1. 调整Spring Security XML配置

先禁用默认的frame-options自动配置,引入自定义的头写入器:

<security:headers>
    <!-- 禁用默认的全局X-Frame-Options配置 -->
    <security:frame-options disabled="true"/>
    <!-- 引入自定义的X-Frame-Options写入逻辑 -->
    <security:header ref="customXFrameOptionsHeaderWriter"/>
    <!-- 可选:引入CSP兼容配置 -->
    <security:header ref="cspFrameAncestorsHeaderWriter"/>
    <!-- 其余原有安全头配置保持不变,如content-type-options、cache-control等 -->
</security:headers>

2. 配置自定义头写入器

你可以选择Java Config或者纯XML配置两种方式:

方式一:Java Config配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.web.header.HeaderWriter;
import org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter;
import org.springframework.security.web.header.writers.XFrameOptionsHeaderWriter;
import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsMode;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.NegatedRequestMatcher;
import org.springframework.security.web.util.matcher.OrRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import java.util.Arrays;
import java.util.List;

@Configuration
public class SecurityHeaderConfig {
    // 自定义需要放开iframe限制的路径列表
    private static final List<String> ALLOW_IFRAME_PATHS = Arrays.asList(
            "/public/embed/**",
            "/share/page/**"
    );

    @Bean
    public HeaderWriter customXFrameOptionsHeaderWriter() {
        // 构建放开路径的匹配规则
        RequestMatcher allowIframeMatcher = new OrRequestMatcher(
                ALLOW_IFRAME_PATHS.stream()
                        .map(AntPathRequestMatcher::new)
                        .toArray(RequestMatcher[]::new)
        );
        // 非放开路径应用SAMEORIGIN策略
        RequestMatcher sameOriginPathMatcher = new NegatedRequestMatcher(allowIframeMatcher);

        return new DelegatingRequestMatcherHeaderWriter(
                sameOriginPathMatcher,
                new XFrameOptionsHeaderWriter(XFrameOptionsMode.SAMEORIGIN)
        );
    }

    // 可选:现代浏览器CSP兼容配置,允许任意来源嵌入放开路径
    @Bean
    public HeaderWriter cspFrameAncestorsHeaderWriter() {
        RequestMatcher allowIframeMatcher = new OrRequestMatcher(
                ALLOW_IFRAME_PATHS.stream()
                        .map(AntPathRequestMatcher::new)
                        .toArray(RequestMatcher[]::new)
        );
        return new DelegatingRequestMatcherHeaderWriter(
                allowIframeMatcher,
                (request, response) -> response.setHeader(
                        "Content-Security-Policy",
                        "frame-ancestors *;"
                )
        );
    }
}

方式二:纯XML Bean配置

如果不想使用Java Config,可以直接在XML中声明相关Bean:

<!-- 配置需要放开的路径匹配规则 -->
<bean id="allowIframeMatcher" class="org.springframework.security.web.util.matcher.OrRequestMatcher">
    <constructor-arg>
        <list>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/public/embed/**"/>
            </bean>
            <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                <constructor-arg value="/share/page/**"/>
            </bean>
        </list>
    </constructor-arg>
</bean>

<!-- 配置需要应用SAMEORIGIN的路径规则 -->
<bean id="sameOriginPathMatcher" class="org.springframework.security.web.util.matcher.NegatedRequestMatcher">
    <constructor-arg ref="allowIframeMatcher"/>
</bean>

<!-- 配置SAMEORIGIN头写入器 -->
<bean id="sameOriginFrameWriter" class="org.springframework.security.web.header.writers.XFrameOptionsHeaderWriter">
    <constructor-arg value="SAMEORIGIN"/>
</bean>

<!-- 自定义X-Frame-Options写入器 -->
<bean id="customXFrameOptionsHeaderWriter" class="org.springframework.security.web.header.writers.DelegatingRequestMatcherHeaderWriter">
    <constructor-arg ref="sameOriginPathMatcher"/>
    <constructor-arg ref="sameOriginFrameWriter"/>
</bean>

纯XML配置CSP写入器时,自定义一个实现HeaderWriter接口的简单类完成CSP头写入即可,逻辑和Java Config版本一致。

3. 验证逻辑

服务启动后:

  • 访问普通业务页面,响应头存在X-Frame-Options: SAMEORIGIN,第三方站点无法通过iframe嵌入
  • 访问配置的放开路径,响应头无X-Frame-Options字段,配置CSP的场景下会返回Content-Security-Policy: frame-ancestors *;,可被任意第三方站点正常嵌入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 01:39:19