Django CSRF认证的几种解决方案


Posted in Python onMarch 03, 2020

什么是CSRF

浏览器在发送请求的时候,会自动带上当前域名对应的cookie内容,发送给服务端,不管这个请求是来源A网站还是其它网站,只要请求的是A网站的链接,就会带上A网站的cookie。浏览器的同源策略并不能阻止CSRF攻击,因为浏览器不会停止js发送请求到服务端,只是在必要的时候拦截了响应的内容。或者说浏览器收到响应之前它不知道该不该拒绝。

攻击过程

用户登陆A网站后,攻击者自己开发一个B网站,这个网站会通过js请求A网站,比如用户点击了某个按钮,就触发了js的执行。

防止攻击

  • Double Submit Cookie

攻击者是利用cookie随着http请求发送的特性来攻击。但攻击者不知道 cookie里面是什么。

Django中是在表单中加一个隐藏的 csrfmiddlewaretoken,在提交表单的时候,会有 cookie 中的内容做比对,一致则认为正常,不一致则认为是攻击。由于每个用户的 token 不一样,B网站上的js代码无法猜出token内容,对比必然失败,所以可以起到防范作用。

  • Synchronizer Token

和上面的类似,但不使用 cookie,服务端的数据库中保存一个 session_csrftoken,表单提交后,将表单中的 token 和 session 中的对比,如果不一致则是攻击。

这个方法实施起来并不困难,但它更安全一些,因为网站即使有 xss 攻击,也不会有泄露token的问题。

Django使用CsrfViewMiddleware中间件进行CSRF校验,默认开启防止csrf(跨站点请求伪造)攻击,在post请求时,没有携带csrf字段,导致校验失败,报403错误。那么我们如何解决这种403错误呢?

解决方法

1. 去掉项目的CSRF验证

Django CSRF认证的几种解决方案

注释掉此段代码即可,但是不推荐此方式,将导致我们的网站完全无法防止CSRF攻击。

2. 前端表单中增加csrf信息

<form enctype="multipart/form-data" method="post" action="{% url 'add_data' %}">
  {% csrf_token %}
</form>

一定要注意后端使用render而不要使用render_to_response进行渲染,这样前端就会有csrf_token变量,前端cookies中也会出现csrftoken数据,然后在HTML中使用即可。这种方式只限制在form表单中使用,ajax请求不支持。

3. 指定请求去掉CSRF校验

可以只针对指定的路由去掉CSRF校验,这也分为两种情况:

FBV:以函数实现路由处理

# 导入,可以使此次请求忽略csrf校验
from django.views.decorators.csrf import csrf_exempt

# 在处理函数加此装饰器即可
@csrf_exempt
def add_data(request):
  result = {}
  # TODO

  return HttpResponse(result)

CBV:以类实现路由处理

from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator


class IndexView(View):
  @method_decorator(csrf_exempt)
  def dispatch(self, request, *args, **kwargs):
    return super().dispatch(request, *args, **kwargs)

  def get(self, request, *args, **kwargs):
    return render(request, 'home.html')

  def post(self, request, *args, **kwargs):
    data = request.POST.get('data')
    qr_path = gen_qrcode(data)
    return HttpResponse(qr_path)

或者用下面的方式,把装饰器放在类外面

from django.views import View
from django.views.decorators.csrf import csrf_exempt
from django.utils.decorators import method_decorator


@method_decorator(csrf_exempt, name='dispatch')
class IndexView(View):
  def get(self, request, *args, **kwargs):
    return render(request, 'home.html')

  def post(self, request, *args, **kwargs):
    data = request.POST.get('data')
    qr_path = gen_qrcode(data)
    return HttpResponse(qr_path)

4. 为所有请求添加csrf校验数据(推荐)

以上方式都有限制,适用范围比较窄,我们需要一种可以一劳永逸的方式:让所有请求都携带csrf数据。因为我们是使用Django模板渲染前端页面的,所以一般会先定义一个base.html,其他页面通过{% extends "base.html" %}来引入使用,那么在base.html中添加ajax的全局钩子,在请求时添加csrf数据即可。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>{% block title %}首页{% endblock %}</title>
  <link rel="stylesheet" href="{% static 'css/base.css'%}">
  <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
  <script>
    $.ajaxSetup({
      data: {
        csrfmiddlewaretoken: '{{ csrf_token }}'
      }
    })
  </script>
  {% block css %}
  {% endblock %}
</head>
<body>

到此这篇关于Django CSRF认证的几种解决方案的文章就介绍到这了,更多相关Django CSRF认证 内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python实现百度关键词排名查询
Mar 30 Python
Python 冒泡,选择,插入排序使用实例
Feb 05 Python
python 类对象和实例对象动态添加方法(分享)
Dec 31 Python
教你用一行Python代码实现并行任务(附代码)
Feb 02 Python
python实现m3u8格式转换为mp4视频格式
Feb 28 Python
python方法生成txt标签文件的实例代码
May 10 Python
读取json格式为DataFrame(可转为.csv)的实例讲解
Jun 05 Python
python读取文件名并改名字的实例
Jan 07 Python
详解python pandas 分组统计的方法
Jul 30 Python
Python tkinter和exe打包的方法
Feb 05 Python
Pytorch学习之torch用法----比较操作(Comparison Ops)
Jun 28 Python
解决pytorch 保存模型遇到的问题
Mar 03 Python
python实现电子词典
Mar 03 #Python
python关于变量名的基础知识点
Mar 03 #Python
python生成13位或16位时间戳以及反向解析时间戳的实例
Mar 03 #Python
python 插入日期数据到Oracle实例
Mar 02 #Python
Python datetime 格式化 明天,昨天实例
Mar 02 #Python
Python MySQL 日期时间格式化作为参数的操作
Mar 02 #Python
记一次pyinstaller打包pygame项目为exe的过程(带图片)
Mar 02 #Python
You might like
PHP函数utf8转gb2312编码
2006/12/21 PHP
PHP压缩html网页代码(清除空格,换行符,制表符,注释标记)
2012/04/02 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
详解PHP导入导出CSV文件
2014/11/03 PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
2019/04/02 PHP
Yii框架参数配置文件params用法实例分析
2019/09/11 PHP
laravel框架使用极光推送消息操作示例
2020/02/15 PHP
Prototype最新版(1.5 rc2)使用指南(1)
2007/01/10 Javascript
解决ExtJS在chrome或火狐中正常显示在ie中不显示的浏览器兼容问题
2013/01/11 Javascript
nodejs实现的一个简单聊天室功能分享
2014/12/06 NodeJs
基于Jquery代码实现手风琴菜单
2015/11/19 Javascript
用NODE.JS中的流编写工具是要注意的事项
2016/03/01 Javascript
浅谈Sublime Text 3运行JavaScript控制台
2016/06/06 Javascript
jQuery实现的网格线绘制方法
2016/06/20 Javascript
关于vue.js弹窗组件的知识点总结
2016/09/11 Javascript
jQuery ajax MD5实现用户注册即时验证功能
2016/10/11 Javascript
jquery结合html实现中英文页面切换
2016/11/29 Javascript
完美实现js选项卡切换效果(一)
2017/03/08 Javascript
基于jQuery中ajax的相关方法汇总(必看篇)
2017/11/08 jQuery
详解刷新页面vuex数据不消失和不跳转页面的解决
2018/01/30 Javascript
详解JS数值Number类型
2018/02/07 Javascript
Angular ng-animate和ng-cookies用法详解
2018/04/18 Javascript
webpack4.x打包过程详解
2018/07/18 Javascript
详解JavaScript 异步编程
2020/07/13 Javascript
详解微信小程序轨迹回放实现及遇到的坑
2021/02/02 Javascript
[01:11:11]Alliance vs RNG 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
Python多线程编程(六):可重入锁RLock
2015/04/05 Python
举例详解Python中threading模块的几个常用方法
2015/06/18 Python
详解Python 数据库 (sqlite3)应用
2016/12/07 Python
Python使用pylab库实现绘制直方图功能示例
2018/06/01 Python
Python eval的常见错误封装及利用原理详解
2019/03/26 Python
windows10环境下用anaconda和VScode配置的图文教程
2020/03/30 Python
CSS3实现同时执行倾斜和旋转的动画效果
2016/10/27 HTML / CSS
副董事长岗位职责
2014/04/02 职场文书
全国法院系统开展党的群众路线教育实践活动综述(全文)
2014/10/25 职场文书
Android studio 简单计算器的编写
2022/05/20 Java/Android