zoukankan      html  css  js  c++  java
  • Django进阶之CSRF

    简介

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

    全局:

    中间件 django.middleware.csrf.CsrfViewMiddleware

    局部:

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

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

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

    原理

    当用post提交数据的时候,django会去检查是否有一个csrf的随机字符串,如果没有就会报错,这也是之前我们一直将其注释的原因,错误如下:

    在django内部支持生成这个随机字符串

    通过form提交

    在form表单里面需要添加{% csrf_token %},如下所示:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/cmdb/login/" method="POST">
            {% csrf_token %}
            <input type="text" name="username" placeholder="用户名">
            <input type="password" name="pwd" placeholder="密码">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

     这样当你查看页面源码的时候,可以看到form中有一个input是隐藏的

    总结原理:当用户访问login页面的时候,会生成一个csrf的随机字符串,并且cookie中也存放了这个随机字符串,当用户再次提交数据的时候会带着这个随机字符串提交,如果没有这个随机字符串则无法提交成功

    cookie中存放的csrftoken如下图

    通过ajax提交

    因为cookie中同样存在csrftoken,所以可以在js中通过:

    $.cooke("cstftoken")获取

    如果通过ajax进行提交数据,这里提交的csrftoken是通过请求头中存放,需要提交一个字典类型的数据,即这个时候需要一个key。

    在views中的login函数中:from django.conf import settings,然后打印print(settings.CSRF_HEADER_NAME)

    这里需要注意一个问题,这里导入的settings并不是我们在项目文件下看到的settings.py文件,这里是是一个全局的settings配置,而当我们在项目目录下的settings.py中配置的时候,我们添加的配置则会覆盖全局settings中的配置

    print(settings.CSRF_HEADER_NAME)打印的内容为:HTTP_X_CSRFTOKEN

    这里的HTTP_X_CSRFTOKEN是django在X_CSRF的前面添加了HTTP_,所以实际传递的是就是X_CSRFtoken,而在前端页面的ajax传递的时候由于不能使用下划线所以传递的是X-CSRFtoken

    下面是在前端ajax中写的具体内容:

        $("#btn1").click(function () {
            $.ajax({
                url:"/login/",
                type:"POST",
                data:{"usr":"root","pwd":"123"},
                headers:{ "X-CSRFtoken":$.cookie("csrftoken")},
                success:function (arg) {
    
                }
            })
        })

    但是如果页面中有多个ajax请求的话就在每个ajax中添加headers信息,所以可以通过下面方式在所有的ajax中都添加

            $.ajaxSetup({
                beforeSend:function (xhr,settings) {
                    xhr.setRequestHeader("X-CSRFtoken",$.cookie("csrftoken"))
                }
            });

    这样就会在提交ajax之前执行这个方法,从而在所有的ajax里都加上这个csrftoken

    这里的xhr是XMLHttpRequest的简写,ajax调用的就是这个方法

    如果想要实现在当get方式的时候不需要提交csrftoken,当post的时候需要,实现这种效果的代码如下:

            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);
                    }
                }
            });

    这样就实现了当GET|HEAD|OPTIONS|TRACE这些方式请求的时候不需要提交csrftoken

    总结

    1、    csrf在ajax提交的时候通过请求头传递的给后台的

    2、    csrf在前端的key为:X-CSRFtoken,到后端的时候django会自动添加HTTP_,并且最后为HTTP_X_CSRFtoken

    3、    csrf在form中提交的时需要在前端form中添加{%csrftoken%}

  • 相关阅读:
    C# 常用小点
    WebClient下载文件
    redis常见错误处理
    win2008R2环境配置
    C#程序员知识体系
    js中json的添加和指定位置的删除
    关于本博客的美化
    箭头函数中可改变this作用域,回调函数用箭头函数this指向page,自定义事件用箭头函数this指向undefined
    json_decode 和 json_encode 区别
    tp6中使用微信支付sdk
  • 原文地址:https://www.cnblogs.com/cyfiy/p/10239038.html
Copyright © 2011-2022 走看看