• Django中与CSRF相关的内容


    Django中与CSRF相关的内容

    1.什么是CSRF?

    ​ CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。

    2.Django下的CSRF认证机制

    ​ django 第一次响应来自某个客户端的请求时,会在服务器端随机生成一个 csrftoken值,把这个 csrftoken 放在 cookie 里。然后每次请求都带着这个值过来完成校验。

    token字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret。官方文档中说到,检验token时,只比较secret是否和cookie中的secret值一样,

    而不是比较整个token。django会验证表单中的token和cookie中token是否能解出同样的secret,secret一样则本次请求合法,这样就能避免被 CSRF 攻击。

    ​ 例如:在html 中, 为每个post请求的form 表单增加一个 {% csrf_token %} 标签,它的功能其实是给form表单增加一个隐藏的input标签。服务端收到请求后,

    django 会对这个请求的 cookie 里的 csrftoken 字段的值和提交的表单里的 csrfmiddlewaretoken 字段的值进行处理,比较secret是否一样,secret一样则本次请求合法。

    3.具体的实现方法

    django通过中间件 django.middleware.csrf.CsrfViewMiddleware 来防止跨站请求伪造。

    #settings.py
    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',#csrf的认证
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    3-1 form表单当中附加csrftoken

      #为每个post请求的form 表单增加一个 {% csrf_token %} 标签,如果不添加,post请求的时候你会发现一个 Forbidden的错误
        
        <form action="" method="post" id="loginForm" novalidate="novalidate">
        
        {% csrf_token %}#
        
        <div>
          <input type="text" name="username" class="username" placeholder="用户名" autocomplete="off">
        </div>
        <div>
          <input type="password" name="password" class="password" placeholder="密码" oncontextmenu="return false"
                 onpaste="return false">
        </div>
        <button id="submit" type="submit">登 陆</button>
        <span style="color: red;">{{ error }}</span>
      </form>
    

    3-2 Ajax的post请求设置csrf_token的方式

    方式1:
        通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。
        
        data:{
            
            csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(), #form表单里必须写{% csrf_token %}#}
    
        },
    
    方式2:
     data:{
           
            csrfmiddlewaretoken:"{{ csrf_token }}", #form表单里不用写{% csrf_token %}  模板语法替换产生
    
        },
            
    
    #示例:
     <script src="{% static 'jquery.js' %}"></script>
        
        #基于jQuery的实现
        <script>
        	$('#btn').click(function () {
                
                $.ajax({ 
                    
                    url:"{% url 'login' %}", 
                    type:'post' ,
                    data:{	
                        username:$('[name=username]').val(),
                        password:$('[name=password]').val(),
                        
                        csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val(),#form表单里必须写 {% csrf_token %}#}--方式1
                        	#或
                        csrfmiddlewaretoken:"{{ csrf_token }}", #form表单里不用写 {% csrf_token %}--方式2 
                    },
    
                    success:function(res){	
                        var resStr = JOSN.parse(res);
                        console.log(res,typeof res);	
                    }
                })
            })
            
        </script>
    
    方式3:通过获取返回的cookie中的字符串,放置在请求头中发送。
    注意:需要引入一个jquery.cookie.js插件,jquery操作cookie。下载地址 https://plugins.jquery.com/cookie/
        
        jquery.cookie.js基于jquery;先引入jquery,再引入:jquery.cookie.js;
    
    <script src="{% static 'jquery.js' %}"></script>
    <script src="{% static 'jquery.cookie.js' %}"></script>
    
    $.ajax({
        
        url:'/test/',
        type:'post',
    	headers:{"X-CSRFToken":$.cookie('csrftoken')}, #从Cookie取csrftoken,并设置到请求头headers中
    
        #ajax里面的headers参数,自定制请求头,可以将csrf_token加在这里,我们发contenttype类型数据的时候,csrf_token就可以这样加
     
    })
    
    
    注意:
    
      1.如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。
    
      2.如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。-->不是所有请求都有csrftoken这个cookie键值对
    
      3.这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。
        
    
    django.views.decorators.csrf import ensure_csrf_cookie
    
    @ensure_csrf_cookie  #强制给请求对应的响应添加csrftoken这个cookie键值对
    def login(request):
        pass
    

    3-3 CSRF Token相关装饰器

    from django.views.decorators.csrf import csrf_exempt,csrf_protect
        
      csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置csrfToken全局中间件。
      csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。
    
    示例1:   
    #views.py
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    # @csrf_exempt
    @csrf_protect
    def login(request):
        if request.method == 'GET':
            return render(request,'login.html')
        else:
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'zhangsan' and password == '1234':
    
                return HttpResponse('OK')
            else:
                return redirect('login')
            
     #login.html
    <form action="/login/" method="post">
      用户名: <input type="text" name="username">
      密码: <input type="password" name="password">
      <input type="submit">
    </form>
    
    #settings.py
        MIDDLEWARE = [
             'django.middleware.csrf.CsrfViewMiddleware',   
        ]
        
    【1】settings中设置了全局中间件,在login.html中不设置{% csrf_token %},当post提交数据时,Forbidden (403)
    	如果在FBV的函数上使用csrf_exempt装饰器,可以成功提交数据。
        
    【2】settings中没有设置全局中间件,当post提交数据时可以成功提交。如果在FBV的函数上使用csrf_exempt装饰器,Forbidden (403)。
    
    
    
    示例2:注意csrf-token装饰器的特殊性,在CBV模式下它只能加在dispatch上面。
    	 添加装饰器的格式必须为@method_decorator(),括号里面为装饰器的函数名
        
    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    from django.utils.decorators import method_decorator
    
    
    #@method_decorator(csrf_exempt, name='dispatch')
    class HomeView(View):
        
        @method_decorator(csrf_exempt)
        def dispatch(self, request, *args, **kwargs):
            return super(HomeView, self).dispatch(request, *args, **kwargs)
    
        def get(self, request):
            return render(request, "home.html")
    
        def post(self, request):
            print("Home Viw POST method...")
            return redirect("/index/")
    
  • 相关阅读:
    正则表达式验证银行卡号
    正则表达式验证银行卡号
    正则表达式验证手机号
    正则表达式验证手机号
    好用的手机浏览器
    jmeter(三)跨线程组调用token
    jmeter(二)ant报告模板下载与使用
    1-5JSON数据解析
    1-3HTTP协议基础
    1-2接口测试概述
  • 原文地址:https://www.cnblogs.com/xiaomage666/p/11312682.html
Copyright © 2020-2023  润新知