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

我是打算在php网站中的一个HTML文件使用iframe标签调用django网站时遇到的问题,这句话说得好像有点繁琐,就是使用iframe时遇到的问题。查了很多相关资料,又说php网站的,有说html中没有设置,有说apache中需要配置,我全部尝试一遍之后都没有解决,后知后觉,发现django中间件问题。先了解一下背景知识。

1.同源策略

什么叫同源?

URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。相反,只要协议,域名,端口有任何一个的不同,就被当作是跨域。

e.g. 对于http://store.company.com/dir/page.html进行同源检测:

URL 结果 原因
http://store.company.com/dir2/other.html 成功 仅路径不同
http://store.company.com/dir/inner/another.html 成功 仅路径不同 
https://store.company.com/secure.html 失败 协议不同
http://store.company.com:81/dir/etc.html 失败 端口不同
http://news.company.com/dir/other.html 失败 主机名不同

 

同源策略  Same-Origin-Policy(SOP)

浏览器采用同源策略,禁止页面加载或执行与自身来源不同的域的任何脚本。换句话说浏览器禁止的是来自不同源的"document"或脚本,对当前"document"读取或设置某些属性。

情景:

比如一个恶意网站的页面通过iframe嵌入了银行的登录页面(二者不同源),如果没有同源限制,恶意网页上的javascript脚本就可以在用户登录银行的时候获取用户名和密码。

 

浏览器中有哪些不受同源限制呢?

<script>、<img>、<iframe>、<link>这些包含 src 属性的标签可以加载跨域资源。但浏览器限制了JavaScript的权限使其不能读、写加载的内容。

2.跨域

跨域是指从一个域的网页去请求另一个域的资源。比如从http://www.baidu.com/ 页面去请求 http://www.google.com 的资源。

 


 

2.跨域

跨域是指从一个域的网页去请求另一个域的资源。比如从http://www.baidu.com/ 页面去请求 http://www.google.com 的资源。

点击劫持保护

点击劫持中间件和装饰器提供了简捷易用的,对点击劫持的保护。这种攻击在恶意站点诱导用户点击另一个站点的被覆盖元素时出现,另一个站点已经加载到了隐藏的frameiframe中。

点击劫持的示例

假设一个在线商店拥有一个页面,已登录的用户可以点击“现在购买”来购买一个商品。用户为了方便,可以选择一直保持商店的登录状态。一个攻击者的站点可能在他们自己的页面上会创建一个“我喜欢Ponies”的按钮,并且在一个透明的iframe中加载商店的页面,把“现在购买”的按钮隐藏起来覆盖在“我喜欢Ponies”上。如果用户访问了攻击者的站点,点击“我喜欢Ponies”按钮会触发对“现在购买”按钮的无意识的点击,不知不觉中购买了商品。

点击劫持的防御

现代浏览器遵循X-Frame-Options协议头,它表明一个资源是否允许加载到frame或者iframe中。如果响应包含值为SAMEORIGIN的协议头,浏览器会在frame中只加载同源请求的的资源。如果协议头设置为DENY,浏览器会在加载frame时屏蔽所有资源,无论请求来自于哪个站点。

Django提供了一些简单的方法来在你站点的响应中包含这个协议头:

  • 一个简单的中间件,在所有响应中设置协议头。
  • 一系列的视图装饰器,可以用于覆盖中间件,或者只用于设置指定视图的协议头。

如何使用

为所有响应设置X-Frame-Options

要为你站点中所有的响应设置相同的X-Frame-Options值,将'django.middleware.clickjacking.XFrameOptionsMiddleware'设置为 MIDDLEWARE_CLASSES

MIDDLEWARE_CLASSES = (
    ...
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ...
)

这个中间件可以在startproject生成的设置文件中开启。

通常,这个中间件会为任何开放的HttpResponse设置X-Frame-Options协议头为SAMEORIGIN。如果你想用 DENY来替代它,要设置X_FRAME_OPTIONS

X_FRAME_OPTIONS = 'DENY'

使用这个中间件时可能会有一些视图,你并不想为它设置X-Frame-Options协议头。对于这些情况,你可以使用一个视图装饰器来告诉中间件不要设置协议头:

from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_exempt

@xframe_options_exempt
def ok_to_load_in_a_frame(request):
    return HttpResponse("This page is safe to load in a frame on any site.")

为每个视图设置 X-Frame-Options

Django提供了以下装饰器来为每个基础视图设置X-Frame-Options协议头。

from django.http import HttpResponse
from django.views.decorators.clickjacking import xframe_options_deny
from django.views.decorators.clickjacking import xframe_options_sameorigin

@xframe_options_deny
def view_one(request):
    return HttpResponse("I won't display in any frame!")

@xframe_options_sameorigin
def view_two(request):
    return HttpResponse("Display in a frame if it's from the same origin as me.")

注意你可以在中间件的连接中使用装饰器。使用装饰器来覆盖中间件。

限制

X-Frame-Options协议头只在现代浏览器中保护点击劫持。老式的浏览器会忽视这个协议头,并且需要 其它点击劫持防范技巧

支持 X-Frame-Options 的浏览器

  • Internet Explorer 8+
  • Firefox 3.6.9+
  • Opera 10.5+
  • Safari 4+
  • Chrome 4.1+

以上是django能否被iframe使用的情况,如果你想能被其他网站直接使用,就将django网站的setting文件中的

'django.middleware.clickjacking.XFrameOptionsMiddleware',

屏蔽掉就好

我的问题已经解决。但是网上仍有很多解释,我感觉碰到的原因可能不同,我这次也记录一下:

在apache 中配置:

先讲一下 X-Frame-Options的作用,赋值有如下三种:

(1)DENY:不能被嵌入到任何iframe或frame中。

(2)SAMEORIGIN:页面只能被本站页面嵌入到iframe或者frame中。

(3)ALLOW-FROM uri:只能被嵌入到指定域名的框架中。

 

防止某些重要网页被其他网站框架导入,可以给页面增加X-Frame-Options响应头,这样浏览器会依据X-Frame-Options的值来控制iframe框架的页面是否允许加载显示出来,IE下的效果如下(此内容无法再框架中显示。为了帮助保护在此网站中输入的信息安全,此内容的发行者不允许在框架中显示该信息),其他非IE核心浏览器会显示空白内容。

动态页添加X-Frame-Options响应头代码在此详细附上设置过程

1>开启Apache的扩展headers_module,
2>在Apache配置文件的空白行加上一下代码:
Header always append X-Frame-Options SAMEORIGIN
完成以上部分,重启Apache服务即可审查页面出现如下代码表示设置成功

 

参考:https://www.html.cn/archives/5141

https://blog.csdn.net/wizardforcel/article/details/48415577

https://www.cnblogs.com/xhz-dalalala/p/5259965.html

展开阅读全文

没有更多推荐了,返回首页