一、csrf简介
什么是csrf
csrf:Cross-site request forgery 跨网站请求伪造
当你登录某网站后,你的浏览器其他受感染的网站发起了操作你网站的请求,这时候你的cookie会被携带到服务器上,服务器无法识别访问者是否正确,从而接收受感染网站的请求(详情参考该链接http://www.cnblogs.com/hyddd/...)
如何防御:
让非读取请求(非GET,HEAD等http方法)携带一个特别的字段,每次请求的时候带上它,对它进行验证,如果正确,则继续其他操作。
这个验证可以有多种方式,比如以下两个例子:
生成一个随机字符串,放在浏览器cookie里,然后post上来的表单或者http header中携带上该字段,服务验证是否相同。
是对sessionid进行运算生成字符串,服务器也进行运算,如果相同则信任请求。其原理都是以伪造请求无法读取,修改http请求报文为基础。
二、csrf token使用
form表单
非读取请求大多是进行数据操作。常见的数据操作是提交表单,为了安全,Django和Flask提供了csrf token进行保护。只需要在template
中引入{{csrf_token}}
即可
ajax提交
如果需要使用ajax提交,方法也很简单。Django为例,只要读取cookie,在http请求头中添加自定义字段X-CSRFToken即可实现csrf验证。
三、颗粒度选择
细心的你可能发现,使用ajax提交后csrf token没有更新。
Django,Flask的Form表单默认每次请求后更新csrf token,也就是说每个request更新一次request,使用起来无压力,很方便。然而使用的ajax提交的方式其实是每个session更新一次。那两者有和不同,有没有安全问题呢?
答案是没必要每个请求都更新一次csrf token的,它不会带来任何安全上的提升,有些时候还会带来不必要的麻烦。比如你在浏览器的标签页中同时打开你的webapp,此时当一个标签页做提交操作后,会更新cookie中的csrf_token,会让另一个标签页的提交失败。因此,我们只需要每个session维护一个csrf token就够了。
那么,为什么Django它们还要这么费劲呢?其实并不是什么情况下都不需要更新session。当发生重要变化的时候,比如登录,则必须更新csrf_token。
举个例子:攻击者将自己的session id和csrf token注入被入侵者的浏览器时,若不更新csrf token。那么当被入侵者登陆时,攻击者就拥有了被入侵者的账号控制权限。
最新思考:如果csrf_token只在某些页面更新,那么要分散更多精力去在意哪些页面需要csrf_token。比如一个页面不需要登录,同时需要post数据,当用户第一次访问该网站时就来到该界面,那么页面一定需要csrf_token才能post操作。所以,个人建议还是每次更新,这样子省心
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。