• 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>

      

  • 相关阅读:
    Mybatis集成dbcp-java.lang.AbstractMethodError: Method org/apache/commons/dbcp/DelegatingResultSet.isClosed()Z is abstract
    Word 错误提示“此功能看似已中断,并需要修复” 解决
    解决 org.springframework.context.annotation.ConflictingBeanDefinitionException
    IDEA中的JAVA WEB项目启动报错的定位方法
    Oracle数据库中包含CLOB字段表的导出和导入
    idea terminal修改为gitbash多彩
    企业微信如何发红包 企业微信向个人发红包 企业微信群无法发红包 企业微信无法发红包 企业微信无法发红包如何解决
    vue项目中使用ts(typescript)入门教程
    svg / d3-force 中如何给link的label文字加底色
    svg 如何使用滤镜给文字加底色
  • 原文地址:https://www.cnblogs.com/zhangmingda/p/13355791.html
Copyright © 2020-2023  润新知