Django csrf机制

官方文档参考这里

##什么是CSRF

CSRF(Cross-site request forgery)跨站请求伪造,也被称成为“one click attack”或者session riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,并且攻击方式几乎相左。XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

比如可以这样进行攻击:

一个网站用户Bob可能正在浏览聊天论坛,而同时另一个用户Alice也在此论坛中,并且后者刚刚发布了一个具有Bob银行链接的图片消息。设想一下,Alice编写了一个在Bob的银行站点上进行取款的form提交的链接,并将此链接作为图片tag。如果Bob的银行在cookie中保存他的授权信息,并且此cookie没有过期,那么当Bob的浏览器尝试装载图片时将提交这个取款form和他的cookie,这样在没经Bob同意的情况下便授权了这次事务。

##防范措施
对于web站点,将持久化的授权方法(例如cookie或者HTTP授权)切换为瞬时的授权方法(在每个form中提供隐藏field),这将帮助网站防止这些攻击。一种类似的方式是在form中包含秘密信息、用户指定的代号作为cookie之外的验证。

另一个可选的方法是“双提交”cookie。此方法只工作于Ajax请求,但它能够作为无需改变大量form的全局修正方法。如果某个授权的cookie在form post之前正被JavaScript代码读取,那么限制跨域规则将被应用。如果服务器需要在Post请求体或者URL中包含授权cookie的请求,那么这个请求必须来自于受信任的域,因为其它域是不能从信任域读取cookie的。

与通常的信任想法相反,使用Post代替Get方法并不能提供卓有成效的保护。因为JavaScript能使用伪造的POST请求。尽管如此,那些导致对安全产生“副作用”的请求应该总使用Post方式发送。Post方式不会在web服务器和代理服务器日志中留下数据尾巴,然而Get方式却会留下数据尾巴。

尽管CSRF是web应用的基本问题,而不是用户的问题,但用户能够在缺乏安全设计的网站上保护他们的帐户:通过在浏览其它站点前登出站点或者在浏览器会话结束后清理浏览器的cookie。

##如何用 Django 进行防范

Django的csrf机制,它实际就是后台生成一个随机字符串,在你显示表单的时候在表单中加入一个hidden input,比如:

<input type='hidden' name='csrfmiddlewaretoken' value='QtF7jsxQddj5Dj9uKuIs3J7jgm0Bf6sg' />

这个hidden input就是csrftoken在模板中根据后台传过来的随机字符串生成的。

  1. form提交时,会通过隐藏表单的方式提交cookie中的csrftoken记录
  2. 服务器端接到POST请求时,会验证提交的Token和用户cookie的Token值是否一致,如不一致就返回403错误

注意:如果使用的是Django.middleware.csrf.CsrfViewMiddle这个中间件,Django会默认验证每一个post请求,因此所有的表单内都需要加上csrf_token的tag,否则站内提交也会被阻止,除非通过@csrf_exempt装饰器来显式申明不验证token值。