Django CSRF
什么是CSRF
CSRF, Cross Site Request Forgery, 跨站点伪造请求。举例来讲,某个恶意的网站上有一个指向你的网站的链接,如果
某个用户已经登录到你的网站上了,那么当这个用户点击这个恶意网站上的那个链接时,就会向你的网站发来一个请求,
你的网站会以为这个请求是用户自己发来的,其实呢,这个请求是那个恶意网站伪造的
Django提供的CSRF防护机制
django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 token,把这个 token 放在 cookie 里。然后每次 POST 请求都会带上这个 token,
这样就能避免被 CSRF 攻击
- 在返回的 HTTP 响应的 cookie 里,django 会为你添加一个 csrftoken 字段,其值为一个自动生成的 token
- 在所有的 POST 表单时,必须包含一个 csrfmiddlewaretoken 字段 (只需要在模板里加一个 tag, django 就会自动帮你生成,见下面)
- 在处理 POST 请求之前,django 会验证这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值是否一样。如果一样,则表明这是一个合法的请求,否则,这个请求可能是来自于别人的 csrf 攻击,返回 403 Forbidden.
- 在所有 ajax POST 请求里,添加一个 X-CSRFTOKEN header,其值为 cookie 里的 csrftoken 的值
Django里如何使用CSRF防护
- 首先,最基本的原则是:GET 请求不要用有副作用。也就是说任何处理 GET 请求的代码对资源的访问都一定要是“只读“的。
- 要启用 django.middleware.csrf.CsrfViewMiddleware 这个中间件
- 再次,在所有的 POST 表单元素时,需要加上一个 {% csrf_token %} tag
- 在渲染模块时,使用 RequestContext。RequestContext 会处理 csrf_token 这个 tag, 从而自动为表单添加一个名为 csrfmiddlewaretoken 的 input
Django实例
定义urls.py
from django.conf.urls import url from django.contrib import admin from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^csrf/', views.csrf), ]
定义views.py
from django.shortcuts import render,HttpResponse def csrf(request): return render(request,'csrf.html')
定义csrf.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="/static/jquery.min.js"></script> <script src="/static/jquery.cookie.js"></script> </head> <body> <form action="/csrf/" method="post"> {% csrf_token %} #普通的form提交需要加 {% csrf_token %} <input type="text" name="v"/> <input type="submit" valu ="提交"/> </form> <input type="button" value="Ajax提交" onclick="DoAjax();" /> #ajax提交,csrf <script> var csrftoken = $.cookie('csrftoken'); function csrfSafeMethod(method) { return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ #这步骤的意思是所有的ajax提交都会先走这条配置,就不用每个ajax提交都配置CSRF了 beforeSend: function(xhr,settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain){ xhr.setRequestHeader("X-CSRFToken",csrftoken); } } }); function DoAjax() { $.ajax({ url: '/csrf/', type: 'POST', data: {'k1':'v1'}, success: function (callback) { console.log(callback) } }) } </script> </body> </html>