zoukankan      html  css  js  c++  java
  • Django-CSRF跨站请求伪造

    跨站请求伪造
        CSRF的全称是`Cross-site request forgery`,简单的意思就是用户在可信网站登录后获得可信cookie,未退出之前,访问了一个恶意网站,恶意网站夹带攻击性代码要求访问一个第三方网站,浏览器在接收到恶意网站的请求后,在用户不知情的情况下携带安全网站给的Cookie信息,向其发出请求。可信网站并不知道该请求其实是由恶意网站发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自恶意网站的恶意代码被执行
    
    Django是如何防范CSRF的

    猛戳

    我们来看看CsrfViewMiddleware这个中间件的源码的一段内容

    ...
    request_csrf_token = ""
    if request.method == "POST":
        try:
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '') # POST请求是在这里获取到的
        except IOError:
            # Handle a broken connection before we've completed reading
            # the POST data. process_view shouldn't raise any
            # exceptions, so we'll ignore and serve the user a 403
            # (assuming they're still listening, which they probably
            # aren't because of the error).
            pass
    
    if request_csrf_token == "":
        # Fall back to X-CSRFToken, to make things easier for AJAX,
        # and possible for PUT/DELETE.
        request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '') # ajax请求是在获取的
    
    request_csrf_token = _sanitize_token(request_csrf_token)
    if not _compare_salted_tokens(request_csrf_token, csrf_token):
        return self._reject(request, REASON_BAD_TOKEN)
    
    ...
    

    当我们手动输出settings.CSRF_HEADER_NAME的结果是这样的:

    from django.conf import settings
    print(settings.CSRF_HEADER_NAME)
    >>> HTTP_X_CSRFTOKEN
    

    Django使用django.middleware.csrf.CsrfViewMiddleware这一个中间件来完成验证的。在django中防御csrf攻击的方式有两种:

    1. 在form表单中添加csrf_token
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
    
        </style>
    </head>
    <body>
    <div>
        <form action="/login/" method="post">
            {% csrf_token %}
            <input type="text" name="user">
            <input type="text" name="pwd">
            <input type="submit" value="提交">
        </form>
    </div>
    <script>
    
    </script>
    </body>
    </html>
    

    在form中加上这个{% csrf_token %}后其实他的本质是生成一个隐藏的input标签,并且input的value值是服务器端给网页get的时候生成的一个随机字符串,如下所示:

    ![](https://img2020.cnblogs.com/blog/1119052/202003/1119052-20200319130508084-1070406822.png)
    在form提交的时候顺带将这个值发送给服务器做验证
    2. 在header中添加X-CSRFToken
    • 当我们使用一般的ajax提交的时候
    <script src="/static/jquery-1.12.4.js"></script> 
    <script src="/static/jquery.cookie.js"></script>
    <script>
        $(function () {
            $('#btn').click(function () {
                $.ajax({
                    url:'/login/',
                    type:'POST',
                    data:$('#f1').serialize(),
                    success:function () {
                    }
                })
            })
        })
    </script>
    
    

    这样写ajax也会出现403CSRF verification failed. Request aborted.

    那么我们的ajax就应该在header中加上CSRF_HEADER_NAME对应的值HTTP_X_CSRFTOKEN,但是由于django会在header的字段的首部自动加上HTTP_来作为区分,所以我们应该添加的真正值是X_CSRFTOKEN,但是又由于请求头中不能加下划线,所以只能写成这样了X-CSRFTOKEN,官方的书写方式是X-CSRFtoken,但是这两种都是可以的。

    通过js来获取csrftoken这个cookie并添加到header中

    正确的ajax请求应该是这样的

    <script src="/static/jquery-1.12.4.js"></script> 
    <script src="/static/jquery.cookie.js"></script>
    <script>
        $(function () {
            $('#btn').click(function () {
                $.ajax({
                    url:'/login/',
                    type:'POST',
                    headers:{"X-CSRFtoken": $.cookie('csrftoken'),}
                    data:$('#f1').serialize(),
                    success:function (arg) {
                        location.href="/index/"
                    }
                })
            })
        })
    </script>
    
    
    3.将页面中所有的ajax请求都添加这个headers
    $.ajaxSetup({
       beforeSend: function(xhr,settings){
           xhr.setRequestHeader('X-CSRFtoken', $.cookie('csrftoken'));
       }
    });
    
    
    django中选择使用CSRF

    部分设定:from django.views.decorators.csrf import csrf_exempt,csrf_protect

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

    全局设定:
    使用中间件django.middleware.csrf.CsrfViewMiddleware

  • 相关阅读:
    JavaScript常用函数和方法
    Django中csrf错误
    LVS+Keepalived负载均衡配置
    CSP-S2019 游记
    三角函数公式整理
    LGOJP3193 [HNOI2008]GT考试
    BZOJ3790. 神奇项链
    BZOJ4241: 历史研究
    LGOJP2051 [AHOI2009]中国象棋
    AT2000 Leftmost Ball
  • 原文地址:https://www.cnblogs.com/forsaken627/p/12521970.html
Copyright © 2011-2022 走看看