Django CSRF认证的几种解决方案
什么是CSRF
浏览器在发送请求的时候,会自动带上当前域名对应的cookie内容,发送给服务端,不管这个请求是来源A网站还是其它网站,只要请求的是A网站的链接,就会带上A网站的cookie。浏览器的同源策略并不能阻止CSRF攻击,因为浏览器不会停止js发送请求到服务端,只是在必要的时候拦截了响应的内容。或者说浏览器收到响应之前它不知道该不该拒绝。
攻击过程
用户登陆A网站后,攻击者自己开发一个B网站,这个网站会通过js请求A网站,比如用户点击了某个按钮,就触发了js的执行。
防止攻击
- DoubleSubmitCookie
攻击者是利用cookie随着http请求发送的特性来攻击。但攻击者不知道cookie里面是什么。
Django中是在表单中加一个隐藏的csrfmiddlewaretoken,在提交表单的时候,会有cookie中的内容做比对,一致则认为正常,不一致则认为是攻击。由于每个用户的token不一样,B网站上的js代码无法猜出token内容,对比必然失败,所以可以起到防范作用。
- SynchronizerToken
和上面的类似,但不使用cookie,服务端的数据库中保存一个session_csrftoken,表单提交后,将表单中的token和session中的对比,如果不一致则是攻击。
这个方法实施起来并不困难,但它更安全一些,因为网站即使有xss攻击,也不会有泄露token的问题。
Django使用CsrfViewMiddleware中间件进行CSRF校验,默认开启防止csrf(跨站点请求伪造)攻击,在post请求时,没有携带csrf字段,导致校验失败,报403错误。那么我们如何解决这种403错误呢?
解决方法
1.去掉项目的CSRF验证
注释掉此段代码即可,但是不推荐此方式,将导致我们的网站完全无法防止CSRF攻击。
2.前端表单中增加csrf信息
{%csrf_token%}
一定要注意后端使用render而不要使用render_to_response进行渲染,这样前端就会有csrf_token变量,前端cookies中也会出现csrftoken数据,然后在HTML中使用即可。这种方式只限制在form表单中使用,ajax请求不支持。
3.指定请求去掉CSRF校验
可以只针对指定的路由去掉CSRF校验,这也分为两种情况:
FBV:以函数实现路由处理
#导入,可以使此次请求忽略csrf校验 fromdjango.views.decorators.csrfimportcsrf_exempt #在处理函数加此装饰器即可 @csrf_exempt defadd_data(request): result={} #TODO returnHttpResponse(result)
CBV:以类实现路由处理
fromdjango.viewsimportView fromdjango.views.decorators.csrfimportcsrf_exempt fromdjango.utils.decoratorsimportmethod_decorator classIndexView(View): @method_decorator(csrf_exempt) defdispatch(self,request,*args,**kwargs): returnsuper().dispatch(request,*args,**kwargs) defget(self,request,*args,**kwargs): returnrender(request,'home.html') defpost(self,request,*args,**kwargs): data=request.POST.get('data') qr_path=gen_qrcode(data) returnHttpResponse(qr_path)
或者用下面的方式,把装饰器放在类外面
fromdjango.viewsimportView fromdjango.views.decorators.csrfimportcsrf_exempt fromdjango.utils.decoratorsimportmethod_decorator @method_decorator(csrf_exempt,name='dispatch') classIndexView(View): defget(self,request,*args,**kwargs): returnrender(request,'home.html') defpost(self,request,*args,**kwargs): data=request.POST.get('data') qr_path=gen_qrcode(data) returnHttpResponse(qr_path)
4.为所有请求添加csrf校验数据(推荐)
以上方式都有限制,适用范围比较窄,我们需要一种可以一劳永逸的方式:让所有请求都携带csrf数据。因为我们是使用Django模板渲染前端页面的,所以一般会先定义一个base.html,其他页面通过{%extends"base.html"%}来引入使用,那么在base.html中添加ajax的全局钩子,在请求时添加csrf数据即可。
{%blocktitle%}首页{%endblock%} {%blockcss%} {%endblock%}
到此这篇关于DjangoCSRF认证的几种解决方案的文章就介绍到这了,更多相关DjangoCSRF认证内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。