Django笔记
csrf
一、CSRF介绍
CSRF(Cross-Site Request Forgery,跨站请求伪造)是一种常见的Web安全漏洞,在这种攻击中,攻击者利用已登录用户的身份,在用户不知情的情况下向目标网站发送恶意请求,这些请求可以执行各种操作,例如更改密码、转账等,而这些操作本应是经过用户明确授权的。
- 工作原理:假设用户登录了受信任的网站A,并在未登出的状态下访问了由攻击者控制的恶意网站B。如果网站B包含有特定构造的请求,指向网站A上的敏感操作,则由于浏览器会自动附带与网站A相关的认证信息(如cookies),导致网站A无法区分该请求是否确实来自用户的意图。
- 防御措施 :
- 使用CSRF Token:确保每个请求都携带一个随机生成的token,并且服务器端验证这个token的有效性。
- 双重Cookie防御:通过设置特定的自定义HTTP头部来增加安全性。
- 同源检查:基于HTTP请求的来源进行检查,确保请求是由合法页面发起的。
- 验证码:虽然不是专门针对CSRF的防御手段,但验证码可以有效防止自动化工具发起的CSRF攻击。
二、Django中的CSRF保护
-
默认启用的保护 :Django通过
CsrfViewMiddleware
中间件实现CSRF保护。它会对所有传入的POST、PUT等非安全HTTP方法的请求进行CSRF token验证。 -
如何使用CSRF Token:
-
在HTML表单中添加
{% csrf_token %}
模板标签,以插入隐藏的输入字段,其值为当前用户的CSRF token。html<form action="" method="POST"> <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}"> {# {% csrf_token %} 或者直接使用{% csrf_token %}模板标签即可 #} <table> <tbody> <tr> <td>邮箱:</td> <td><input type="email" name="email"></td> </tr> <tr> <td>密码:</td> <td><input type="password" name="password"></td> </tr> <tr> <td></td> <td><input type="submit" value="登录"></td> </tr> </tbody> </table>
{% csrf_token %}
网页源代码显示如下: -
对于AJAX请求,需要手动将CSRF token添加到请求头中,可以通过JavaScript获取cookie中的CSRF token,并将其作为
X-CSRFToken
头部的一部分发送。js$("#submit-btn").click(function (event) { // 阻止按钮的默认行为,默认是表单发送,要改成Ajax event.preventDefault(); let title = $("input[name='title']").val(); let category = $("#categoryInput").val(); let content = editor.getHtml(); let csrfmiddlewaretoken = $("input[name=csrfmiddlewaretoken]").val(); $.ajax({ url: "/blog/pub", method: "POST", data: { title, category, content, csrfmiddlewaretoken}, success: function (result) { if (result["code"] === 201){ // 获取帖子id let blog_id = result["data"]["blog_id"]; // 跳转到帖子详情页面 window.location = '/blog/' + blog_id; } else { alert(result["message"]); } } }) })
-
-
403错误:
如果在Django中处理POST请求但没有在HTML表单中添加{% csrf_token %}模板标签,并且尝试通过AJAX或其他方式发送这个表单数据,Django的CSRF中间件会阻止这个请求并返回一个403 Forbidden错误。