当前位置: 首页 > 后端技术 > Python

DjangoCSRF认证的几种解决方案

时间:2023-03-25 19:39:28 Python

什么是CSRF?浏览器在发送请求时,会自动带上当前域名对应的cookie内容发送给服务器。如果请求链接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。提交表单后,将表单中的令牌与会话中的令牌进行比较。如果它们不一致,那就是攻击。这种方法实现起来并不难,但是比较安全,因为即使网站有xss攻击,也不会有泄露token的问题。Django使用CsrfViewMiddleware中间件进行CSRF验证。默认情况下启用它以防止csrf(跨站点请求伪造)攻击。当post请求没有携带csrf字段时,校验失败,报403错误。那么我们如何解决这个403错误呢?解决方案1.去掉项目的CSRF验证,把这段代码注释掉,但是不推荐这种方法,我们的网站将完全无法防止CSRF攻击。2.前端表单添加csrf信息{%csrf_token%}必须注意post端使用render而不是render_to_response进行渲染,这样前端就会有csrf_token变量,csrftoken数据也会出现在前端cookie中,然后在HTML中就可以使用了。该方法仅限于在form表单中使用,不支持ajax请求。3、指定请求去除CSRF验证只能去除指定路由的CSRF验证,也分为两种情况:FBV:implementroutingprocessingwithfunctions#import,可以让这个请求从django.views.decorators中忽略csrf验证.csrfimportcsrf_exempt#添加这个装饰器到处理函数@csrf_exemptdefadd_data(request):result={}#TODOreturnHttpResponse(result)CBV:用类实现路由处理fromdjango.viewsimportViewfromdjango.views.decorators.csrfimportcsrf_exemptfromdjango.utils.decoratorsimportmethod_decoratorclassIndexView(View):@method_decorator(csrf_exempt)defdispatch(self,request,*args,**kwargs):返回super().dispatch(request,*args,**kwargs)defget(self,request,*args,**kwargs):返回render(request,'home.html')defpost(self,request,*args,**kwargs):data=request.POST.get('data')qr_path=gen_qrcode(data)returnHttpResponse(qr_path)或使用以下满足hod,将装饰器放在类外fromdjango.viewsimportViewfromdjango.views.decorators.csrfimportcsrf_exemptfromdjango.utils。装饰器导入method_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%}Home{%endblock%}{%blockcss%}{%endblock%}如果你觉得我的文章还可以,你可以关注我的微信公众号查看更多实战文章:Python爬虫实战之路也可以扫描下方二维码加我微信公众号