Django进阶之CSRF的解决办法

发表于:2017-7-26 16:09

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:cls超    来源:博客

  简介
  django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。
  全局:
  中间件 django.middleware.csrf.CsrfViewMiddleware
  局部:
  @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
  @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
  注意:from django.views.decorators.csrf import csrf_exempt,csrf_protect
  原理
  当用post提交数据的时候,django会去检查是否有一个csrf的随机字符串,如果没有就会报错,这也是之前我们一直将其注释的原因,错误如下:
  在django内部支持生成这个随机字符串
  通过form提交
  在form表单里面需要添加{%csrf_token%}
  这样当你查看页面源码的时候,可以看到form中有一个input是隐藏的
  总结原理:当用户访问login页面的时候,会生成一个csrf的随机字符串,,并且cookie中也存放了这个随机字符串,当用户再次提交数据的时候会带着这个随机字符串提交,如果没有这个随机字符串则无法提交成功
  cookie中存放的csrftoken如下图
   
  通过ajax提交
  因为cookie中同样存在csrftoken,所以可以在js中通过:
  $.cooke("cstftoken")获取
  如果通过ajax进行提交数据,这里提交的csrftoken是通过请求头中存放,需要提交一个字典类型的数据,即这个时候需要一个key。
  在views中的login函数中:from django.conf import settings,然后打印print(settings.CSRF_HEADER_NAME)
  这里需要注意一个问题,这里导入的settings并不是我们在项目文件下看到的settings.py文件,这里是是一个全局的settings配置,而当我们在项目目录下的settings.py中配置的时候,我们添加的配置则会覆盖全局settings中的配置
  print(settings.CSRF_HEADER_NAME)打印的内容为:HTTP_X_CSRFTOKEN
  这里的HTTP_X_CSRFTOKEN是django在X_CSRF的前面添加了HTTP_,所以实际传递的是就是X_CSRFtoken,而在前端页面的ajax传递的时候由于不能使用下划线所以传递的是X_CSRFtoken
  下面是在前端ajax中写的具体内容:
      $("#btn1").click(function () {
          $.ajax({
              url:"/login/",
              type:"POST",
              data:{"usr":"root","pwd":"123"},
              headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
              success:function (arg) {
              }
          })
      })
  但是如果页面中有多个ajax请求的话就在每个ajax中添加headers信息,所以可以通过下面方式在所有的ajax中都添加
          $.ajaxSetup({
              beforeSend:function (xhr,settings) {
                  xhr.setRequestHeader("X-CSRFtoken",$.cookie("csrftoken"))
              }
          });
  这样就会在提交ajax之前执行这个方法,从而在所有的ajax里都加上这个csrftoken
  这里的xhr是XMLHttpRequest的简写,ajax调用的就是这个方法
   
  如果想要实现在当get方式的时候不需要提交csrftoken,当post的时候需要,实现这种效果的代码如下:
   function csrfSafeMethod(method) {
              // these HTTP methods do not require CSRF protection
              return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
          }
          $.ajaxSetup({
              beforeSend: function(xhr, settings) {
                  if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                      xhr.setRequestHeader("X-CSRFToken", csrftoken);
                  }
              }
          });
  这样就实现了当GET|HEAD|OPTIONS|TRACE这些方式请求的时候不需要提交csrftoken
  总结
  1、csrf在ajax提交的时候通过请求头传递的给后台的
  2、csrf在前端的key为:X-CSRFtoken,到后端的时候django会自动添加HTTP_,并且最后为HTTP_X_CSRFtoken
  3、csrf在form中提交的时需要在前端form中添加{%csrftoken%}
《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号