in a frame because it set 'X-Frame-Options' to 'deny'.

2021-01-14  乐帮网

web

X-Frame-Options HTTP 响应头是用来给浏览器指示是否允许页面嵌套到在 <frame></iframe> 或<object> 中显示。网站可以使用这个响应头,来避免自己网站的页面被一些不法分子嵌套到自己的网站中去做坏事儿。

这个头X-Frame-Options 包含三种值 :
DENY    表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。
SAMEORIGIN   表示该页面可以在相同域名页面的 frame 中展示。
ALLOW-FROM uri  表示uri的页面可以在指定来源的 frame 中展示。

由于X-Frame-Options的默认大多也是DENY默认值大多是DENY,由此带来了上述问题。
各大Web平台修改,允许指定嵌入方法汇总如下:

(1)在使用spring Security时,可以通修改配置如下:

<security:http auto-config="true" use-expressions="true">
    <security:headers>
        <security:frame-options policy="SAMEORIGIN"/>
    </security:headers>

(2)使用apache托管的站点 在apache httpd.conf中末尾增加如下配置:

Header set X-Frame-Options "allow-from SAMEORIGIN"

(3)使用Spring Boot框架时可以通以以下配置实现修改X-Frame-Options的目的:

<http>
    <!-- ... -->
    <headers>
        <frame-options policy="SAMEORIGIN" />
    </headers>
</http>

也可以通过如下代码实现:

@EnableWebSecurity
public class WebSecurityConfig extends
        WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) {
        http
            // ...
            .headers(headers -> headers
                .frameOptions(frameOptions -> frameOptions
                    .sameOrigin()
                )
            );
    }
}

(4)原生的Java Web项目可过添加头解决

response.setHeader("X-Frame-Options", "SAMEORIGIN");

也可以通过配置实现:

 <filter>  
    <filter-name>httpHeaderSecurity</filter-name>  
    <filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>  
    <init-param>  
        <param-name>antiClickJackingOption</param-name>  
        <param-value>SAMEORIGIN</param-value>  
    </init-param>  
    <async-supported>true</async-supported>  
</filter>  

(5)在nginx下托管的站点可以通过如下配置修改

在Nginx的配置文件中把下面这行添加到 'http', 'server' 或者 'location' 的配置中:

add_header X-Frame-Options SAMEORIGIN;

(6)NetFramework开发的站点部署在IIS中时,可通过修改Web.config修改如下:

<system.webServer>
     ...
      <httpProtocol>
        <customHeaders>
          <add name="X-Frame-Options" value="SAMEORIGIN" />
        </customHeaders>
      </httpProtocol>
     ...
    </system.webServer>

(7)在开发Chrome 浏览器的插件时,也会遇到上述问题,可以个时候可以得用Chrome自身提示的webRequest  API实现,例如:

chrome.webRequest.onHeadersReceived.addListener(
    function(info) {
        var headers = info.responseHeaders;
        for (var i=headers.length-1; i>=0; --i) {
            var header = headers[i].name.toLowerCase();
            if (header == 'x-frame-options' || header == 'frame-options') {
                headers.splice(i, 1); // Remove header
            }
        }
        return {responseHeaders: headers};
    },
    {
        urls: [ '*://*/*' ], // Pattern to match all http(s) pages
        types: [ 'sub_frame' ]
    },
    ['blocking', 'responseHeaders']
);

(8)NetCore站点实现的一种方式,可通过中间件来实现修改响应头。静态文件可以通过官方提示的资料来去掉X-Frame-Options这个头,写法如下 :

 app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = ctx =>
                {
                    // Requires the following import:
                    // using Microsoft.AspNetCore.Http;
                    foreach (var header in ctx.Context.Response.Headers)
                    {
                        if (header.Key.Equals("X-Frame-Options"))
                        {
                            ctx.Context.Response.Headers.Remove(header);
                        }
                    }
                    ctx.Context.Response.Headers.Add("X-Frame-Options", "SAMEORIGIN");
                }
            });

博客园里提供了一个中间件写法地址:https://www.cnblogs.com/yuchenghao/p/11412518.html
主要的代码如下:

/// <summary>
    /// 响应头的增删集合
    /// </summary>
    public class SecurityHeadersPolicy
    {
        public IDictionary<string, string> SetHeaders { get; }
             = new Dictionary<string, string>();

        public ISet<string> RemoveHeaders { get; }
            = new HashSet<string>();
    }
/// <summary>
    /// 中间件实现
    /// </summary>
    public class SecurityHeadersMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly SecurityHeadersPolicy _policy;

        public SecurityHeadersMiddleware(RequestDelegate next, SecurityHeadersPolicy policy)
        {
            _next = next;
            _policy = policy;
        }

        public async Task Invoke(HttpContext context)
        {
            IHeaderDictionary headers = context.Response.Headers;

            foreach (var headerValuePair in _policy.SetHeaders)
            {
                headers[headerValuePair.Key] = headerValuePair.Value;
            }

            foreach (var header in _policy.RemoveHeaders)
            {
                headers.Remove(header);
            }

            await _next(context);
        }
    }
 /// <summary>
    /// 响应头的增删方法
    /// </summary>
    public class SecurityHeadersBuilder
    {
        private readonly SecurityHeadersPolicy _policy = new SecurityHeadersPolicy();
        public SecurityHeadersBuilder AddCustomHeader(string header, string value)
        {
            _policy.SetHeaders[header] = value;
            return this;
        }
        public SecurityHeadersBuilder RemoveHeader(string header)
        {
            _policy.RemoveHeaders.Add(header);
            return this;
        }
        public SecurityHeadersPolicy Build()
        {
            return _policy;
        }
    }
   /// <summary>
    /// 中间件拓展方法
    /// </summary>
    public static class UseSecurityHeaders
    {
        public static IApplicationBuilder UseSecurityHeadersMiddleware(this IApplicationBuilder app, SecurityHeadersBuilder builder)
        {
            SecurityHeadersPolicy policy = builder.Build();
            return app.UseMiddleware<SecurityHeadersMiddleware>(policy);
        }
    }

最后在startup的Configure方法中使用中间件:

 //允许iframe嵌入资源
            app.UseSecurityHeadersMiddleware(new SecurityHeadersBuilder()
              .AddCustomHeader("X-Frame-Options", "SAMEORIGIN")
            );

除了上述博客园文章的参考还参考了如下地址:

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
https://docs.spring.io/spring-security/site/docs/current/reference/html5/
https://docs.microsoft.com/zh-cn/aspnet/core/fundamentals/static-files?view=aspnetcore-2.2

相关文章:

X-Frame-Options 浏览器兼容性

公众号二维码

关注我的微信公众号
在公众号里留言交流
投稿邮箱:1052839972@qq.com

庭院深深深几许?杨柳堆烟,帘幕无重数。
玉勒雕鞍游冶处,楼高不见章台路。
雨横风狂三月暮。门掩黄昏,无计留春住。
泪眼问花花不语,乱红飞过秋千去。

欧阳修

付款二维码

如果感觉对您有帮助
欢迎向作者提供捐赠
这将是创作的最大动力