前端同事内嵌网页,发现个别网页无法显示并提示,”in a frame because it set ‘X-Frame-Options’ to ‘sameorigin’”的报错(如:youku视频)
一、预备知识点
1.同源策略
1.1 什么是同源
URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。相反,只要协议,域名,端口有任何一个的不同,就被当作是跨域。
1.2 同源策略(Same-Origin-Policy(SOP))
浏览器默认采用同源策略,禁止页面加载或执行与自身来源不同的域的任何脚本。
场景:
一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。
浏览器中有哪些不受同源限制呢?
<script>、<img>、<iframe>、<link>这些包含 src 属性的标签可以加载跨域资源。但浏览器限制了JavaScript的权限使其不能读、写加载的内容。
2.跨域
跨域是指从一个域的网页去请求另一个域的资源。
3.点击劫持
这种攻击在恶意站点诱导用户点击另一个站点的被覆盖元素时出现,另一个站点已经加载到了隐藏的frame或iframe中。
点击劫持的示例
假设一个在线商店拥有一个页面,已登录的用户可以点击“购买”按钮来购买一个商品。用户为了方便,可以选择一直保持商店的登录状态。一个攻击者的站点可能在他们自己的页面上会创建一个“收藏”按钮,并且在一个透明的iframe中加载商店的页面,把“购买”的按钮隐藏起来覆盖在“收藏”上。如果用户访问了攻击者的站点,点击“收藏”按钮会触发对“购买”按钮的无意识的点击,不知不觉中便购买了商品。
二、X-Frame-Options
1.什么是X-Frame-Options
X-Frame-Options HTTP 响应头是用来给浏览器 指示允许一个页面 可否在<frame>,<iframe>, <embed> 或者 <object> 中展现的标记。站点可以通过确保网站没有被嵌入到别人的站点里面,从而避免 clickjacking 攻击。
2.X-Frame-Options有什么用
用于点击劫持的防御:现代浏览器遵循X-Frame-Options协议头(RFC 7034规范),根据协议头不同配置,从而决定一个资源是否允许加载到frame或者iframe中。
3.如何配置
Note: 设置 meta 标签是无效的!例如 没有任何效果。
只有当像下面示例那样设置 HTTP 头 X-Frame-Options 才会生效。
3.1 X-Frame-Options配置参数
| 参数 | 含义 | 命令 |
|---|---|---|
| deny | 表示该页面不允许在 frame 中展示,即便是在相同域名的页面中嵌套也不允许。 | add_header X-Frame-Options deny; |
| sameorigin | 表示该页面可以在相同域名页面的 frame 中展示。 | add_header X-Frame-Options sameorigin; |
| allow-from | 表示该页面可以在指定来源的 frame 中展示。 | add_header X-Frame-Options allow-from https://example.com/; |
| allowall | 允许所有站点内嵌展示。 | add_header X-Frame-Options allowall; |
3.2 配置 Apache
配置 Apache 在所有页面上发送 X-Frame-Options 响应头,需要把下面这行添加到 ‘site’ 的配置中:
Header always set X-Frame-Options "sameorigin"
要将 Apache 的配置 X-Frame-Options 设置成 deny , 按如下配置去设置你的站点:
Header set X-Frame-Options "deny"
要将 Apache 的配置 X-Frame-Options 设置成 allow-from,在配置里添加:
Header set X-Frame-Options "allow-from https://example.com/"
3.3 配置 nginx
配置 nginx 发送 X-Frame-Options 响应头,把下面这行添加到 ‘http’, ‘server’ 或者 ‘location’ 的配置中:
例如:
1.修改配置
add_header X-Frame-Options allowall always;

2.nginx指定目下生效配置
cd ../usr/sbin/
./nginx -s reload
3.检测是否配置成功
curl -I http://192.168.2.2:5091

3.4 配置 IIS
配置 IIS 发送 X-Frame-Options 响应头,添加下面的配置到 Web.config 文件中:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="sameorigin" />
</customHeaders>
</httpProtocol>
...
</system.webServer>
3.5 配置 HAProxy
配置 HAProxy 发送 X-Frame-Options 头,添加这些到你的前端、监听 listen,或者后端的配置里面:
rspadd X-Frame-Options:\ sameorigin
或者,在更加新的版本中:
http-response set-header X-Frame-Options sameorigin
3.6 配置 Express
要配置 Express 可以发送 X-Frame-Options header,你可以用借助了 frameguard 来设置头部的 helmet。在你的服务器配置里面添加:
const helmet = require('helmet');
const app = express();
app.use(helmet.frameguard({ action: "sameorigin" }));
或者,你也可以直接用 frameguard:
const frameguard = require('frameguard')
app.use(frameguard({ action: 'sameorigin' }))
4.测评

三、最终结果
1.猜测优酷开启了同源策略(sameorigin),所以我们的iframe无法内嵌其网页
2.解决方案,亲测可以