什么是X-Frame-Options
HTTP有一个特殊的Response响应头字段X-Frame-Options
,它可以指示是否允许浏览器在<iframe>
、<frame>
、<embed>
和<object>
里渲染。许多站点可以利用这个头字段避免clickjacking的攻击,这是一个浏览器安全问题,简单来说就是可以使用程序模拟用户恶意点击页面相关的DOM元素,比如在登录页面点击登录按钮等等,造成页面短时间内登录动作频繁造成服务器有压力从而达到攻击目的。所以才会有[CSRF: Cross-site request forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery)
出现,当然这不是今天讨论的话题,感兴趣的朋友可以去看看。
X-Frame-Options
有两个值
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
DENY
,就是禁止显示在<iframe>
、<frame>
、<embed>
和<object>
标签SAMEORIGIN
,相比上一条就是同源的情况下可以显示
默认不响应这个字段的话就是没有任何限制
iframe嵌入第三方服务
有时候,你需要iframe嵌入一些第三方服务在你的页面里,正好第三方服务做了这个限制,比如Grafana,Gitlab等为了安全,默认情况下会Respoonse Headers带X-Frame-Options: DENY
,如以下摘自Gitlab某个页面的Response,它带了X-Frame-Options: DENY
信息。
Response
:status: 200
Content-Type: text/html; charset=utf-8
Vary: Accept-Encoding
Pragma: no-cache
X-XSS-Protection: 1; mode=block
Content-Encoding: gzip
Referrer-Policy: strict-origin-when-cross-origin, strict-origin-when-cross-origin
Cache-Control: max-age=0, private, must-revalidate, no-store
Date: Wed, 27 May 2020 09:42:22 GMT
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
ETag: W/"d0183a9b27acd2a2571c038069950af1"
x-runtime: 0.159561
Server: nginx
x-download-options: noopen
x-permitted-cross-domain-policies: none
x-request-id: Jbod8TtfHl2
Strict-Transport-Security: max-age=31536000
x-ua-compatible: IE=edge
这种情况下,你要是使用iframe嵌入Gitlab页面,浏览器会在读到Response里存在X-Frame-Options: DENY
信息后停止渲染,并在console打出一条错误信息
Refused to display 'http://gitlab.example.com' in a frame because it set 'X-Frame-Options' to 'deny'.
解决这个方法只能看一下第三方服务有没有提供相关的配置文件,比如Grafana
的配置文件里就有一个allow_embedding = true | false
字段用于配置是否在Response里带X-Frame-Options: DENY
信息。
使用反向代理
有的时候,第三方服务没有提供相关的配置,也没有源码,这个时候可以增加一层反向代理解决X-Frame-Options
相关问题,下面以Nginx为例子
如果你希望强行加上X-Frame-Options
限制别人iframe嵌入,可以这么干
nginx.conf
...
location /third-service/ {
add_header 'X-Frame-Options' 'DENY';
proxy_pass http://third-service.com;
}
...
如果你不想被X-Frame-Options
受限制,但第三方服务强行带了这个X-Frame-Options
字段,你也可以在Response的时候把这个头字段给去掉
nginx.conf
...
location /third-service/ {
proxy_hide_header X-Frame-Options;
proxy_pass http://third-service.com;
}
...
以上配置在Nginx Response回客户端之前把上游响应的头字段X-Frame-Options
移除掉,这样就接触限制了
当然,一山有一山高,你可以在前面加一个Nginx反向代理添加X-Frame-Options
头字段,别人也可以在架一层Nginx把你的X-Frame-Options
给移除掉。