zoukankan      html  css  js  c++  java
  • 六、CsrfViewMiddleware

    CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。

    你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。

    关于更多关于CSRF的介绍,请参考以下链接:

    http://www.cnblogs.com/hyddd/archive/2009/04/09/1432744.html

    https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#CSRF_Specific_Defense

    Django应对CSRF攻击的机制是通过csrftoken(HTTP请求)或者csrftoken + HTTP_REFERER(HTTPS)来实现的。

    CSRF防护的粒度主要有两类:
    1、全局使能,所有视图(view)使能CSRF认证。

    这个主要通过CsrfViewMiddleware中间件来实现。当该中间件添加到setting.py的MIDDLEWARE列表内时,即使能了CSRF中间件,CSRF中间件处理的时机主要是在处理完所有中间件的process_request(),即将进行视图渲染之前,以及response返回给客户端的数据中添加cookie的csrftoken信息之前。这两个功能分别通过process_view()和process_response()完成。当csrf中间件被使能时,所有http请求,都必须对csrttoken进行验证和处理,所有POST,DELETE等安全操作请求必须显示携带csrftoken(或通过http-body,或通过http-header的HTTP_X_CSRFTOKEN),其余安全操作,如'GET', 'HEAD', 'OPTIONS', 'TRACE'只需要在cookie中携带服务器返回给客户的csrftoken即可完成CSRF验证。

    2、基于单个视图(view)。

    这个主要通过基于CsrfViewMiddleware的装饰器函数实现,具体来说是csrf_exempt(),csrf_protect()等实现,前者将某个视图排除在CSRF验证之外,即无需进行CSRF验证,后者对某个视图进行强制验证。具体有多种方案:

    方案一

    ('^my_page/$', csrf_exempt(my_page_view), {'template': 'my_page.html'})

    方案二

    @csrf_exempt

    def my_page_view (self, request, extra_context=None):

    方案三

    if not getattr(view, 'csrf_exempt', False):

       inner = csrf_protect(inner)

    通过走读CsrfViewMiddleware的代码,不难明白CSRF验证的工作原理,总结起来主要有以下几条:

    1、'GET', 'HEAD', 'OPTIONS', 'TRACE'这些安全的操作方式,无需CSRF验证,如果有必要的话,只需做CSRF的更新操作,即当客户cookie携带了新的csrftoken,需要更新当前csrftoken。

    2、POST和DELETE操作需要CSRF验证。特别是HTTPS请求,更需要HTTP_REFERER的双重确认机制。

    3、对于POST操作,客户需要在http-body中携带csrfmiddlewaretoken(64B),且应该跟http头部中cookie解析到的cstftoken(64B)保持一致(两者解密之后对应的secret一样)。这个地方让我觉得很奇怪,为什么要同时携带着两者呢? 这两串数据不一样,但是解密之后又是一样的,中间到底有什么关联?

    def _unsalt_cipher_token (token)      /*解密*/

    salt = token[:32]

    cipher = token[32:]

    secret = FUNC_inverse(salt, token)  

    def _salt_cipher_secret(secret):       /*加密*/

           salt = _get_new_csrf_string()    /*salt为随机生成的32B字符串*/

           cipher = FUNC(secret, salt)

           return salt(32B) + cipher(32B)

    加密,解密涉及到的过程表示成框图如下:

     4、在Django的CSRF处理机制中,当通过admin/login登录后,会强制更新csrftoken并返回给客户,客户在接下来的请求中,可以在http头部携带非POST请求)携带该token即可。

    def rotate_token(request):

    # Changes the CSRF token in use for a request - should be done on login for security purposes.

    request.META.update({

            "CSRF_COOKIE_USED": True,

            "CSRF_COOKIE": _get_new_csrf_token(),

        })

    request.csrf_cookie_needs_reset = True

    在CsrfViewMiddleware的process_response()接口中,如果发现csrf_cookie_needs_reset标志位为真,即对返回的response更新cookie中的csrftoken字段。

    客户端和服务器csrf_token交互的过程如下图所示:

     

    其中,第一次,客户请求的cookie或者不携带csrftoken(箭头上面情况,通常是用户首次登陆),或者携带旧的csrftoken(箭头下面情况),如果是普通的安全操作(如GET)等,不对CSRF进行更新,只会更新其过期时间等属性,因此在返回的response中,csrftoken依然是old_token,但是携带了set-cookie头,通知客户端,cookie更新了。

    第二次,客户通过POST admin/login登录服务器,这时后需要在http请求的http-body中携带csrfmiddlewaretoken,此时,头部携带cookie中携带的csrftoken依然是old_token,服务器登录成功后,强制更新csrftoken为new_token,并返回给客户端。

    第三次,后续的客户请求,都采用新的new_token发起请求,如果csrftoken没有更新,则返回的response中cookie不再携带csrftoken信息。

  • 相关阅读:
    webstorm创建和搭建vue项目
    win10企业版激活方法
    Jquery使用规范(一)
    Json序列化循环引用的问题
    后台调用存储过程
    将金额人民币转化为大写 C#
    谷歌分辨率扩展程序的添加
    MVC 删除文件
    MVC C# 调用存储过程
    XML 转换 lits<>
  • 原文地址:https://www.cnblogs.com/fbli/p/5928100.html
Copyright © 2011-2022 走看看