跳转到内容
主菜单
主菜单
移至侧栏
隐藏
导航
首页
最近更改
随机页面
MediaWiki帮助
代码酷
搜索
搜索
中文(中国大陆)
外观
创建账号
登录
个人工具
创建账号
登录
未登录编辑者的页面
了解详情
贡献
讨论
编辑“︁
Django跨站请求伪造保护(CSRF Protection)
”︁(章节)
页面
讨论
大陆简体
阅读
编辑
编辑源代码
查看历史
工具
工具
移至侧栏
隐藏
操作
阅读
编辑
编辑源代码
查看历史
常规
链入页面
相关更改
特殊页面
页面信息
外观
移至侧栏
隐藏
您的更改会在有权核准的用户核准后向读者展示。
警告:
您没有登录。如果您进行任何编辑,您的IP地址会公开展示。如果您
登录
或
创建账号
,您的编辑会以您的用户名署名,此外还有其他益处。
反垃圾检查。
不要
加入这个!
= Django跨站请求伪造保护(CSRF Protection) = '''跨站请求伪造'''(Cross-Site Request Forgery,CSRF)是一种常见的网络攻击方式,攻击者利用用户已登录的身份,在用户不知情的情况下执行非预期的操作。Django内置了强大的CSRF保护机制,帮助开发者防范此类攻击。 == 什么是CSRF攻击? == CSRF攻击通常发生在以下场景: * 用户登录了某个网站(如银行网站),并在同一浏览器中访问了恶意网站。 * 恶意网站包含一个表单或脚本,向银行网站发送请求(如转账操作)。 * 由于用户已登录,银行网站会认为这是合法请求,导致攻击成功。 Django的CSRF保护机制通过以下方式防御: # 为每个用户会话生成唯一的CSRF令牌(Token)。 # 要求所有修改数据的POST请求必须包含该令牌。 # 服务器验证令牌的有效性,拒绝无效请求。 == Django中的CSRF实现 == === 基本配置 === Django默认启用CSRF中间件。在<code>settings.py</code>中确认以下中间件存在: <syntaxhighlight lang="python"> MIDDLEWARE = [ 'django.middleware.csrf.CsrfViewMiddleware', # 其他中间件... ] </syntaxhighlight> === 在模板中使用CSRF令牌 === 任何包含POST表单的模板必须添加<code>{% csrf_token %}</code>标签: <syntaxhighlight lang="html+django"> <form method="post"> {% csrf_token %} <input type="text" name="username"> <button type="submit">提交</button> </form> </syntaxhighlight> 渲染后的HTML会包含隐藏的CSRF令牌字段: <syntaxhighlight lang="html"> <form method="post"> <input type="hidden" name="csrfmiddlewaretoken" value="32位随机字符串"> <input type="text" name="username"> <button type="submit">提交</button> </form> </syntaxhighlight> === AJAX请求处理 === 对于AJAX请求,需要手动添加CSRF令牌。Django会在cookie中存储CSRF令牌(如果已启用CSRF中间件)。 使用JavaScript(jQuery示例): <syntaxhighlight lang="javascript"> $.ajax({ url: "/api/endpoint/", type: "POST", data: { 'content': "Hello World", 'csrfmiddlewaretoken': getCookie('csrftoken') // 从cookie获取 }, success: function(response) { console.log(response); } }); function getCookie(name) { let cookieValue = null; if (document.cookie && document.cookie !== '') { const cookies = document.cookie.split(';'); for (let i = 0; i < cookies.length; i++) { const cookie = cookies[i].trim(); if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } </syntaxhighlight> == 验证流程 == Django的CSRF验证流程如下: <mermaid> sequenceDiagram participant 客户端 participant 服务器 客户端->>服务器: GET请求(获取表单) 服务器->>客户端: 返回表单+CSRF令牌 客户端->>服务器: POST请求(包含CSRF令牌) 服务器->>服务器: 验证令牌 alt 令牌有效 服务器->>客户端: 200 OK else 令牌无效 服务器->>客户端: 403 Forbidden end </mermaid> == 实际案例 == === 案例1:银行转账攻击 === 假设银行网站有一个转账端点: <syntaxhighlight lang="python"> # views.py(危险!无CSRF保护) def transfer_money(request): if request.method == 'POST': amount = request.POST['amount'] account = request.POST['account'] # 执行转账... return HttpResponse("转账成功") </syntaxhighlight> 攻击者可以构造恶意页面: <syntaxhighlight lang="html"> <!-- 恶意网站 --> <form action="https://bank.com/transfer/" method="POST"> <input type="hidden" name="amount" value="1000"> <input type="hidden" name="account" value="attacker_account"> </form> <script>document.forms[0].submit();</script> </syntaxhighlight> 启用CSRF保护后,这种攻击将失败,因为恶意页面无法获取有效的CSRF令牌。 === 案例2:安全实现 === 正确的Django视图应该: <syntaxhighlight lang="python"> from django.views.decorators.csrf import csrf_protect @csrf_protect def transfer_money(request): if request.method == 'POST': # 自动验证CSRF令牌 amount = request.POST['amount'] account = request.POST['account'] # 执行转账... return HttpResponse("转账成功") # GET请求返回表单 return render(request, 'transfer_form.html') </syntaxhighlight> == 高级配置 == === 豁免特定视图 === 有时需要禁用CSRF保护(如API端点),可以使用<code>@csrf_exempt</code>装饰器: <syntaxhighlight lang="python"> from django.views.decorators.csrf import csrf_exempt @csrf_exempt def api_endpoint(request): # 这个视图不受CSRF保护 return JsonResponse({'status': 'ok'}) </syntaxhighlight> === 自定义错误页面 === 当CSRF验证失败时,Django返回403错误。可以自定义处理: <syntaxhighlight lang="python"> from django.views.decorators.csrf import requires_csrf_token from django.shortcuts import render @requires_csrf_token def my_csrf_failure_view(request, reason=""): return render(request, 'csrf_error.html', {'reason': reason}, status=403) </syntaxhighlight> 在<code>settings.py</code>中配置: <syntaxhighlight lang="python"> CSRF_FAILURE_VIEW = 'myapp.views.my_csrf_failure_view' </syntaxhighlight> == 数学原理 == CSRF令牌通常是随机生成的,其安全性取决于熵值。假设令牌长度为32字节(256位),可能的组合数为: <math> 2^{256} \approx 1.16 \times 10^{77} </math> 这使得暴力破解在计算上不可行。 == 最佳实践 == * 始终为修改数据的请求启用CSRF保护 * 不要通过GET请求修改数据 * 对于API,考虑使用其他认证方式(如Token、JWT) * 保持Django版本更新,获取最新的安全补丁 == 常见问题 == '''Q: 为什么我的表单提交返回403错误?''' A: 可能原因: * 模板中遗漏<code>{% csrf_token %}</code> * 中间件顺序错误(CsrfViewMiddleware应在SessionMiddleware之后) * 使用了缓存表单(CSRF令牌会过期) '''Q: API如何实现CSRF保护?''' A: 推荐方式: * 对于传统API:使用<code>csrf_protect</code>并从cookie/header获取令牌 * 对于现代SPA:使用JWT等无状态认证 通过理解并正确实现Django的CSRF保护,你可以有效防御这类常见的安全威胁,保护用户数据安全。 [[Category:后端框架]] [[Category:Django]] [[Category:Django安全]]
摘要:
请注意,所有对代码酷的贡献均被视为依照知识共享署名-非商业性使用-相同方式共享发表(详情请见
代码酷:著作权
)。如果您不希望您的文字作品被随意编辑和分发传播,请不要在此提交。
您同时也向我们承诺,您提交的内容为您自己所创作,或是复制自公共领域或类似自由来源。
未经许可,请勿提交受著作权保护的作品!
取消
编辑帮助
(在新窗口中打开)