Django点击劫持防护有了吗

wen python案例 2

本文目录导读:

Django点击劫持防护有了吗

  1. 默认防护机制
  2. 检查是否已启用
  3. 配置选项
  4. 如果你的站点需要被嵌入(iframe)
  5. 攻击场景示例(为何需要防护)
  6. 常见问题

是的,Django 自带了点击劫持(Clickjacking)防护机制,它通过 X-Frame-Options HTTP 响应头来实现,默认是开启的。


默认防护机制

Django 的 django.middleware.clickjacking.XFrameOptionsMiddleware 中间件默认会为所有响应添加以下 HTTP 头:

X-Frame-Options: DENY

这个头告诉浏览器:不允许该页面在 <frame><iframe><embed> 中显示,从而防止点击劫持攻击。

检查是否已启用

查看你的 settings.py 文件中的 MIDDLEWARE 配置:

MIDDLEWARE = [
    # ... 其他中间件 ...
    'django.middleware.clickjacking.XFrameOptionsMiddleware',  # 通常默认存在
]

如果没有,需要手动添加(建议放在中间件列表的最后)。

配置选项

1 全局设置 X_FRAME_OPTIONS

settings.py 中,你可以设置全局策略:

# 拒绝所有(最安全)
X_FRAME_OPTIONS = 'DENY'
# 仅允许同源
X_FRAME_OPTIONS = 'SAMEORIGIN'
# 允许指定域名(需要自定义中间件或使用装饰器)
# Django 原生不支持 ALLOW-FROM 的全局设置

2 使用装饰器逐视图控制

如果你需要在特定视图允许页面被嵌入(例如支付回调页面、小工具等),可以使用 Django 提供的装饰器:

from django.views.decorators.clickjacking import xframe_options_exempt, xframe_options_sameorigin, xframe_options_deny
# 允许在 iframe 中显示(完全放开)
@xframe_options_exempt
def my_widget_view(request):
    return render(request, 'widget.html')
# 只允许同源 iframe 嵌入
@xframe_options_sameorigin
def my_api_callback(request):
    return JsonResponse({'status': 'ok'})
# 明确拒绝(覆盖全局设置)
@xframe_options_deny
def sensitive_data_view(request):
    return render(request, 'secret.html')

如果你的站点需要被嵌入(iframe)

如果你确实需要允许别人通过 iframe 加载你的页面(例如提供小部件服务):

  1. 使用 SAMEORIGIN:只允许你自己站点的页面嵌入(例如你后台管理页面包含一个预览框架)
  2. 使用 xframe_options_exempt + CSRF 防护:完全允许嵌入时,需要额外考虑 CSRF 攻击(因为 iframe 中的 cookie 会携带)
  3. 使用 Content-Security-Policy (CSP):Django 没有自带 CSP 中间件,但你可以通过 django-csp 第三方包添加更细粒度的控制:
# pip install django-csp
MIDDLEWARE += ['csp.middleware.CSPMiddleware']
CSP_FRAME_ANCESTORS = ["'self'", "https://trusted-site.com"]

攻击场景示例(为何需要防护)

攻击者构造恶意页面:

<iframe src="https://your-bank.com/transfer?amount=1000&to=hacker" 
        style="opacity:0; position:absolute; top:100px; left:200px; width:500px; height:500px;">
</iframe>
<button id="innocent-button">点我领取红包</button>

用户点击“红包”按钮时,实际点击的是银行转账按钮。X-Frame-Options: DENY 会阻止该页面被加载到 iframe 中,从而阻断攻击。

常见问题

Q: 我设置了 X_FRAME_OPTIONS = 'SAMEORIGIN',但第三方网站还是能嵌入我的页面?

  • 检查是否使用了明确的 @xframe_options_exempt 装饰器覆盖了全局设置
  • 检查是否有反向代理(如 Nginx)覆盖了该响应头

Q: 前端 SPA (单页应用) + Django API 后端

  • Django API 返回的 JSON 响应同样会添加 X-Frame-Options 头(没关系,JSON 不会被嵌入 iframe)
  • 如果渲染的 HTML 页面需要被嵌入,按上述方法配置
需求 配置方法
默认安全(推荐) 保持 XFrameOptionsMiddleware 开启,无需设置
允许同源嵌入 settings.py 设置 X_FRAME_OPTIONS = 'SAMEORIGIN'
特定视图允许嵌入 使用 @xframe_options_exempt 装饰器
精确控制嵌入域名 使用 django-csp 包配置 CSP_FRAME_ANCESTORS

Django 的点击劫持防护是现成的,默认开启,你只需要确保中间件没有被误删除即可。

抱歉,评论功能暂时关闭!