The CSRF middleware and template tag provides easy-to-use protection against Cross Site Request Forgeries. This type of attack occurs when a malicious website contains a link, a form button or some JavaScript that is intended to perform some action on your website, using the credentials of a logged-in user who visits the malicious site in their browser. A related type of attack, ‘login CSRF’, where an attacking site tricks a user’s browser into logging into a site with someone else’s credentials, is also covered.
The first defense against CSRF attacks is to ensure that GET requests (and other ‘safe’ methods, as defined by RFC 7231#section-4.2.1) are side effect free. Requests via ‘unsafe’ methods, such as POST, PUT, and DELETE, can then be protected by following the steps below.
以上描述来自django官方文档种对CSRF中间件的描述,简单的来说,就是一个页面发出的请求必须来自于这个站点。拿银行来说,银行转账的url可能是这样www.xxbank.com/trans
,POST参数为target_id
,money
;如果现在有一个钓鱼网站诱骗用户输入了银行账户和密码,然后在隐藏表单内提交target_id
和money
那么钱就莫名其妙的被转走了。这也就是所谓的CSRF。
django为了解决这个问题,在POST
,PUT
,DELETE
等可以修改数据的方法设置了csrf_token,当用户第一次访问网站的时候,服务端会产生一个随机的安全码作为token,并返回给客户端, 客户端会将token存在cookies里,在进行POST提交的时候,则必须带上这个token,以便于服务器验证。总的来说就是给客户端发令牌, 客户端带着令牌才可以执行操作,否则就返回403.
在前端的form表单里加上csrf_token,模板会默认在表单内增加一个隐藏项(命名为csrfmiddlewaretoken)。
1 | <form action="/login"> |
对于ajax则需要手动去设置参数,在进行数据提交之前,在请求头内加上页面之前发送过来的token。django官方提供了从cookie里获得csrf-token的方法:
1 | //ajax设置csrf_token |
执行上述操作之后,在进行正常的ajax提交即可。
有时候部分浏览器可能拿不到token,这个时候需要使用到装饰器ensure_csrf_cookie
.用来装饰需要使用token的view,确保token在第一次访问时被传递到客户端。
同时,还可以使用 csrf_protecte或csrf_exempt 强制要求一个view使用或不使用CSRF中间件。
默认情况下,token会被放在cookies里,但也可放在session内,可通过settings配置文件修改,但匿名用户是没有session的。