zoukankan      html  css  js  c++  java
  • 跨站请求伪造(scrf)、设置scrf值、CBV加装饰器

    跨站请求伪造(scrf)

    听说过钓鱼网站吗?

    就类似于你搭建了一个跟银行一模一样的web页面
    用户在你的网站转账的时候输入用户名 密码 对方账户
    银行里面的钱确实少了 但是发现收款人变了

    原理:

    你写的form表单中 用户的用户名  密码都会真实的提交给银行后台
    但是收款人的账户却不是用户填的 你暴露给用户的是一个没有name属性的input框
    你自己提前写好了一个隐藏的带有name和value的input框
    

    解决钓鱼网站的策略:

    只要是用户想要提交post请求的页面 我在返回给用户的时候就提前设置好一个随机字符串
    中间件会给前端加上一个隐藏的input框,里面value就是这个随机字符串
    当用户提交post请求的时候  我会自动先取查找是否有该随机字符串 
    如果有 正常提交
    如果没有  直接报403 
    

    所以!!

    那个被我们注释掉的中间件,就是用来校验你有没有这个随机字符串的。

    这就是django自带的东西,你可以理解为,这个中间件不允许的前端post请求,都不能通过这一层校验,要怎样让post请求成功呢,就要让他通过校验。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
        <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
        <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    
    </head>
    <body>
    <h1>我是正儿八经的网站</h1>
    <form action="" method="post">
        {% csrf_token %}
        <p>username:<input type="text" name="username"></p>
        <p>target_user:<input type="text" name="target_user"></p>
        <p>money:<input type="text" name="money"></p>
        <input type="submit">
    </form>
    

    只需要加上 {% csrf_token %} 就可以通过校验了。这是正常form表单提交post请求的时候的做法,还有一种可以提交post的就是 ajax 请求。

    ajax的做法

    方式一、自己现在页面上写 {% csrf_token %} 获取到随机字符串 然后利用标签查找,然后在ajax发送的数据的 data 中加上这个键值对

    data:{'username':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
    

    csrfmiddlewaretoken 这个是要记住的,这个单词

    方式二、

     data:{'username':'jason','csrfmiddlewaretoken':'{{ csrf_token }}'}
    

    这个是django提供的模板语法,但是在前后端分离的时候就不能用了,所以不推荐。

    方式三、导入js,不需要理解这个js代码,这个是从官网上c下来的,只需写一个静态文件,放进去,然后配置静态文件就可以了。建议把这段代码保存在本地。

    function getCookie(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // 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;
    }
    var csrftoken = getCookie('csrftoken');
    
    
    
    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);
        }
      }
    });
    
    <script src="/static/setup.js"></script>
    {#导入这一句就可以了#}
    

    推荐这种。

    学了这个之后,就不用在注释那个中间件了。

    现在又有个需求了,想要让有个视图函数不校验 csrf ,怎么做?

    要导入一个模块

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

    csrf_exempt 是让一个函数绕过校验,不用校验。

    现在突然又发神经有个新的需求,在注释了 csrf 中间件之后,想要校验一个函数,怎么做。

    csrf_protect 让一个函数被校验。

    以上两种都是以装饰器的形式来发挥作用的

    @csrf_exempt #装饰了这个装饰器之后,就可以绕过校验了。不用那个随机字符串了
    def exem(request):
        return HttpResponse('exempt')
    
    @csrf_protect #装饰了这个装饰器就会被校验了。
    def pro(request):
        return HttpResponse('pro')
    
    

    以上是 FBV 型的,那么CBV类型的要怎么写呢?

     装饰器
            csrf_exempt  只有两种装饰的方式
            from django.views.decorators.csrf import csrf_exempt, csrf_protect
            from django.utils.decorators import method_decorator
            # 第一种
            # @method_decorator(csrf_exempt,name='dispatch')
            class MyCsrf(View):
                # 第二种
                @method_decorator(csrf_exempt)
                def dispatch(self, request, *args, **kwargs):
                    return super().dispatch(request,*args,**kwargs)
                def get(self,request):
                    return HttpResponse('hahaha')
                    
            除了csrf_exempt之外 所有的其他装饰器 在CBV上面都有三种方式
            @method_decorator(csrf_protect,name='post') #第一种
            class MyCsrf(View):
                @method_decorator(csrf_protect)#第二种
                def dispatch(self, request, *args, **kwargs):
                    return super().dispatch(request,*args,**kwargs)
                def get(self,request):
                    return HttpResponse('hahaha')
    
                @method_decorator(csrf_protect)#第三种
                def post(self,request):
                    return HttpResponse('post')
    
  • 相关阅读:
    Android的LinearLayout中的权重android:layout_weight
    iPhone尺寸规范
    导出iPhone中安装的APP的iPA文件
    c++ json字符串转换成map管理
    mac 升级EI Capitan后遇到c++转lua时遇到libclang.dylib找不到的错
    sqlite3 数据库使用
    关于flyme5显示不到和卸载不到旧应用解决方法
    cocos2dx 通过jni调用安卓底层方法
    cocos2dx 单张图片加密
    安卓线程使用问题
  • 原文地址:https://www.cnblogs.com/chanyuli/p/11768711.html
Copyright © 2011-2022 走看看