点击劫持中间件和装饰器提供易于使用的保护,以防止 点击劫持 。 当恶意网站欺骗用户点击另一个网站的隐藏元素时,就会发生这种类型的攻击,该元素已被加载到一个隐藏的框架或 iframe 中。
点击劫持的一个例子
假设一家在线商店有一个页面,登录的用户可以点击“立即购买”来购买商品。用户为了方便,选择了保持登录商店。攻击者网站可能会在自己的一个页面上创建一个“I Like Ponies”按钮,并在一个透明的 iframe 中加载商店的页面,使“立即购买”按钮无形中覆盖在“I Like Ponies”按钮上。如果用户访问攻击者的网站,点击“I Like Ponies”将导致无意中点击“立即购买”按钮,并在不知情的情况下购买该商品。
防止点击劫持
现代浏览器尊重 X-Frame-Options HTTP 头,它表明是否允许在框架或 iframe 中加载资源。如果响应包含值为 SAMEORIGIN
的头,那么只有当请求来自同一个网站时,浏览器才会在框架中加载资源。如果头被设置为 DENY
,那么无论请求是由哪个网站发出的,浏览器都会阻止资源在框架中加载。
Django 提供了一些方法来在你的网站的响应中包含这个头:
- 一个在所有响应中设置头的中间件。
- 一组可用于覆盖中间件或仅为某些视图设置头的视图装饰器。
X-Frame-Options
HTTP 头只有在响应中还没有出现的情况下,才会被中间件或视图装饰者设置。
如何使用它
为所有响应设置 X-Frame-Options
要为你的网站的所有响应设置相同的 X-FrameOptions
值,把 'django.middleware.clickjacking.XFrameOptionsMiddleware'
放到 MIDDLEWARE
:
MIDDLEWARE = [
...
'django.middleware.clickjacking.XFrameOptionsMiddleware',
...
]
这个中间件在 startproject
生成的配置文件中启用了。
默认情况下,中间件将为每个传出的 HttpResponse
设置 X- Frame-Options
头为 DENY
。如果你想为这个头设置任何其他的值,可以设置 X_FRAME_OPTIONS
配置:
X_FRAME_OPTIONS = 'SAMEORIGIN'
在使用中间件时,有些视图可能 不希望 设置 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.")
备注
如果你想在框架或 iframe 中提交表单或访问会话 cookie,你可能需要修改 CSRF_COOKIE_SAMESITE
或 SESSION_COOKIE_SAMESITE
配置。
为每个视图设置 X-Frame-Options
。
要在每个视图上设置 X-Frame-Options
头,Django 提供了这些装饰器:
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
的浏览器的 完整列表 。
讨论区