• 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

  • 相关阅读:
    2.12 使用@DataProvider
    2.11 webdriver中使用 FileUtils ()
    Xcode8 添加PCH文件
    The app icon set "AppIcon" has an unassigned child告警
    Launch Image
    iOS App图标和启动画面尺寸
    iPhone屏幕尺寸、分辨率及适配
    Xcode下载失败 使用已购项目页面再试一次
    could not find developer disk image
    NSDate与 NSString 、long long类型的相互转化
  • 原文地址:https://www.cnblogs.com/forsaken627/p/12521970.html
Copyright © 2020-2023  润新知