CSRF(跨站请求伪造)与django项目的预防方法

一、跨站请求伪造(CSRF)的概念

CSRF全称为Cross-site request forgery,中文意为跨站请求伪造。它是指一种网络攻击技术:不法分子盗用身份信息并伪造请求,进行并非你本意的操作。

csrf

  • csrf的案例:

    假设我们在浏览器中逛支付王(就当做是个很垃圾的支付平台,转账连个转账密码确认都没有的那种,但确实是正规平台),且已经登陆。注意!这意味着浏览器保存了用户登录相关的cookie信息

    此时,右下角来了个弹窗,提示可以领取优惠券。但其实就是个病毒弹出的钓鱼网站。而我们又天真地打开了网站。结果页面出现一个按钮:点我领取优惠券。我们不假思索的点了下去,结果账户中的1000块钱被转走。

  • 钱被转走的原因:

    关键在于那个按钮上,它实际上发送的是一个转账给不法分子的http请求(伪造的请求)。由于我们之前已经正常登陆,所以该请求就会携带cookie信息,使钓鱼网站跳过了登录支付王的步骤,再加上支付王没做转账时的密码确认,最终被不法分子转走了我们的钱。

二、django的CSRF令牌

CSRF通常是针对POST方法的!django自带了一种预防CSRF攻击的方法,十分简单好用。

  • 使用方法:

    必须启用'django.middleware.csrf.CsrfViewMiddleware'中间件!该中间件默认是启用的。

    在表单中:

    form标签内部任意位置写入{% csrf_token %}即可:

    <form>
        ……
        {% csrf_token %}
        ……
    </form>
    
  • 预防原理:

    同源策略:现在所有支持JavaScript 的浏览器都会使用这个策略。所谓同源是指,域名,协议,端口相同。保证了一个WEB应用的资源(cookie等)只能被该应用本身访问。

    该模板语法实际上就是生成了一个隐藏的name属性为'csrfmiddlewaretoken'的input输入框,这个input的值就是Django提供给表单的csrf_token。

    csrf_token实质上是一串随机字符串,同表单一起发给客户端,用户提交请求时,附带这个字符串,服务器端进行验证,是否与先前发送的一致,一致则通过请求。 而由于同源策略,恶意网站是得不到这个临时数据的。虽然能通过cookie跳过登录身份验证,却无法跳过csrf_token验证。

三、在ajax中使用csrf_token(jQuery为例)

由于js代码中无法携带隐藏的input框,所以ajax请求中就要使用另外的方法来携带csrf_token。

  • 第一种:

    在页面中写入{% csrf_token %},然后在data对象中,获取模板语法生成的随机字符串,提交给后端(注意键名不要写错):

    <form>
        {% csrf_token %}
    </form>
    
    <script>
    $.ajax({
        url:'',
        type:'POST', 
        data:{"name":"hugh","csrfmiddlewaretoken":$('[name=csrfmiddlewaretoken]').val()}, 
        ……
    })
    </script>
    
  • 第二种:

    将以下代码复制后应用到我们的前端页面,它是django官方提供的获取csrf_token的代码:

    function getCookie(name) {
        let cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            const cookies = document.cookie.split(';');
            for (let i = 0; i < cookies.length; i++) {
                const cookie = cookies[i].trim();
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) === (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
    const csrftoken = getCookie('csrftoken');
    

    如果你安装了js-cookie前端库,那么上面的代码可以简化为:

    const csrftoken = Cookies.get('csrftoken');
    

    然后,在页面中写入{% csrf_token %},在data中将上面代码获取到的scrftoken常量写入即可:

    data: { "name": "hugh", "csrfmiddlewaretoken":csrftoken }
    

四、关于CSRF的装饰器

1. 单独指定需要csrf验证的视图

在settings.py文件中注释掉'django.middleware.csrf.CsrfViewMiddleware'中间件,就关闭了全局的csrf验证。此时,如果想要让某些视图具有csrf验证功能,可以使用csrf_protect装饰器进行装饰:

from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect

@csrf_protect
def my_view(request):
    return render(request, "template.html")

之后,通过该视图的请求就会被进行csrf验证。

2. 单独指定忽略csrf验证的视图

如果开启了全局csrf验证,而某些视图不需要csrf验证,则可以使用csrf_exempt装饰器装饰这些视图:

from django.views.decorators.csrf import csrf_protect, csrf_exempt
from django.utils.decorators import method_decorator

# FBV的装饰和普通函数的装饰方法一样
# CBV的装饰有点特殊,需要通过 method_decorator 方法来装饰 dispatch 方法
class IndexView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super().dispatch(request, *args, **kwargs)
    
    def get(self, request):
        return render(request, 'index.html')

    def post(self, request):
        return redirect(reverse('index'))
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花_城

你的鼓励就是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值