zoukankan      html  css  js  c++  java
  • Django的安全机制 CSRF 跨站请求访问

    跨站请求伪造

    一、简介

    django为用户实现防止跨站请求伪造的功能,通过中间件 django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

    开启此功能后服务端会做两样设置:

      1. 会在cookie中加入 csrftoken字段

      2. 在html模板中 form表单POST请求需加入  {% csrf_token %} 

      注:1. 和2. 生成的字段name和值不一样,但都有效。

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    settings.py

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

    局部:

    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

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

    二、应用

    1、普通表单

    #veiw中设置返回值:
      return render_to_response('Account/Login.html',data,context_instance=RequestContext(request))  
         或者
         return render(request, 'xxx.html', data)
    # html中设置Token:
      {% csrf_token %}

      html中设置的{% crsf_token %} 渲染后在from表单中生成隐藏的input标签

    <input type="hidden" name="csrfmiddlewaretoken" value="ATvEtmpN8CFuc57eFrnGPjMlIgW2pLQUSKkFAc1FhiSrYbwyI8DuMOv1UubPjxuQ">

      注意:html表单中生成的为token名字为:csrfmiddlewaretoken

    2、Ajax

      对于传统的form,可以通过表单的方式将token再次发送到服务端,而对于ajax的话,使用如下方式。

      view.py

    class SessionLogin(View):
        def get(self, request):
            return render(request, 'session_login.html')
    
        def post(self, request):
            u = request.POST.get('username')
            p = request.POST.get('pwd')
            if u != user.get('username'):
                return render(request, 'session_login.html')
            if p == user.get('password'):
                request.session['current_user'] = u
                request.session.set_expiry(10)
                return redirect('/session_index/')    # form表单提交时可以跳转
                # return HttpResponse('OK') # form表单提交时可以跳转
                # return render(request, 'session_index.html')
            else:
                return render(request, 'session_login.html')

      html中ajax发起POST请求

      关键技术:

           获取:$.cookie('csrftoken')  从cookie中获取csrftoken

           设置:$.ajaxSetup({ beforeSend: function (xhr, settings) {xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'))})  //ajax请求前设置csrftoken

           临时设置:$.ajax({ headers:{'X-CSRFtoken': $.cookie('csrftoken') }}, ...)

        <script>
            //获取cookie
            //正则语法验证是否是(GET|HEAD|OPTIONS|TRACE)中的任何一种方法,是则返回true
            function csrfSafeMethod(method) {
                // these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
    
            function submit() {
                let username = $('#username').val();
                let pwd = $('#pwd').val();
                let data = {'username':username,'pwd':pwd};
                $.ajaxSetup({
                    beforeSend: function (xhr, settings) {
                        // 如果HTTP请求Method 非GET|HEAD...等,并且不是跨域请求,则设置'X-CSRFtoken'请求头
                        if(!csrfSafeMethod(settings.type) && !this.crossDomain){
                            xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
                        }
                        //console.log('this', this);
                        //this为当次ajax请求的全部内容实体对象
                        //console.log('settings.type:',settings.type);
                        //settings.type 当次执行请求时的HTTP-Method
                        //console.log('this.crossDomain:',this.crossDomain);
                    }
                });
    
                $.ajax({
                    url:'/session_login/',
                    data:data,
                    type:'POST',
                    {#headers:{'X-CSRFtoken': $.cookie('csrftoken') }, //请求时临时加入CSRFtoken#}
                    success:function (response_data, textStatus, jqXHR) {
                        {#console.log(textStatus);#}
                        {#console.log(jqXHR.statusText);#}
                        {# window.location.href = '/session_index/';#}
                    }
                });
            }
            $('#submit').click(submit)
        </script>

      

  • 相关阅读:
    ajax怎么打开新窗口具体如何实现
    关于springcloud hystrix 执行 hystrix.stream 跳转失败的问题
    Zookeeper 和Eureka比较
    Maven Install报错:Perhaps you are running on a JRE rather than a JDK?
    Oracle11g卸载步骤
    Oracle数据库备份及恢复
    python是如何进行内存管理的?
    python面试题
    json模块与hashlib模块的使用
    随机验证码、打印进度条、文件copy脚本
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/13355791.html
Copyright © 2011-2022 走看看