一、Django的CSRF保护机制
1. 核心原理
- 作用:防止跨站请求伪造(CSRF)攻击,确保表单提交来源可信。
- 实现方式:
- 在模板中使用
{% csrf_token %}
生成一个隐藏的<input>
字段(如csrfmiddlewaretoken
)和一个Cookie
(csrftoken
)。 - 提交表单时,Django会同时验证表单字段和Cookie中的token是否匹配。
- 中间件依赖:由
django.middleware.csrf.CsrfViewMiddleware
实现,需在MIDDLEWARE
配置中启用。
2. 关键流程
<form method="post">{% csrf_token %} <!-- 生成隐藏字段 -->...
</form>
- 生成阶段:首次访问页面时,中间件生成token并注入响应(Cookie + 表单字段)。
- 验证阶段:提交表单时,中间件对比
POST
数据中的token和Cookie中的token,不一致则返回403错误。
3. 特殊场景处理
- AJAX请求:需手动从Cookie读取token并添加到请求头(
X-CSRFToken
)。 - 豁免CSRF保护:用
@csrf_exempt
装饰器标记视图(谨慎使用)。
二、redirect
时附带locals()
与不附带的区别
1. redirect
函数的作用
- 返回HTTP重定向响应(状态码302),不直接渲染模板,而是跳转到新URL。
- 语法:
redirect('view_name')
或 redirect('/url/')
。
2. 错误用法:redirect(locals())
def my_view(request):user = request.usererror = "Invalid input"return redirect('success_page', locals())
- 问题分析:
locals()
返回当前作用域的所有变量(如user
, error
),但redirect
不接受模板上下文参数。- 实际效果:重定向时完全忽略
locals()
中的变量,仅执行URL跳转。 - 若需传递数据,必须通过URL参数(
?key=value
)或Session实现。
3. 正确用法:render(request, template, locals())
def my_view(request):user = request.usererror = "Invalid input"return render(request, 'template.html', locals())
- 与
redirect
的区别: 场景 | redirect(locals()) | render(request, template, locals()) |
---|
HTTP响应类型 | 302重定向 | 200 OK(直接渲染模板) |
数据传递方式 | 无效(数据丢失) | 有效(变量注入模板) |
URL变化 | 浏览器地址栏更新为目标URL | 地址栏不变 |
典型用例 | 提交表单后跳转到结果页 | 渲染包含表单的页面 |
4. 重定向时传递数据的正确方法
三、最佳实践总结
- CSRF安全:
- 所有
POST
表单必须包含{% csrf_token %}
。 - 避免全局禁用CSRF中间件,优先使用
@csrf_exempt
局部豁免。
- 重定向使用规范:
- 禁止在
redirect
中使用locals()
,因其无法传递上下文。 - 需传递数据时,改用Session或URL参数。
- 模板渲染优化:
- 避免滥用
render(..., locals())
,显式传递变量更安全(如render(..., {'user': user}
),防止意外暴露敏感变量。