zoukankan      html  css  js  c++  java
  • Python 24 Django之csrf中间件

    CSRF:跨站请求伪造

    一、两种方式通过csrf校验

    1、在模板中写上{% csrf_token %}

    2、csrf_exempt,csrf_protect装饰器

    from django.views.decorators.csrf import csrf_exempt, csrf_protect
    
    @csrf_exempt  # 如果使用csrf中间件,加上这个装饰器可以直接通过检验
    def login(request):
        return render(xxx)
    
    @csrf_protect  # 如果不使用csrf中间件,加上这个装饰器可以单独进行检验
    def login(request):
        return render(xx)

    二、csrf中间件源码解析

    1、文字版流程

    process_request:

        从请求的cookie中获取csrftoken的值,赋给csrf_token变量,再request.META["CSRF_COOKIE"] = csrf_token

    process_view:

        ① 如果视图加上了csrf_exempt装饰器,不做校验

        ② 如果请求方式是GET / HEAD / OPTION / TRACE中的一种,不做校验

        ③ 其他情况做校验:

            csrf_token = request.META["CSRF_COOKIE"],

            request_csrf_token = ""

            # 首先从form表单中获取csrfmiddlewaretoken的值

      request_csrf_token = request.POST.get("csrfmiddlewaretoken", "")

      # 如果表单中没获取到,则取请求头中获取X-csrftoken的值

      request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, "")

      

      将request_csrf_token和csrf_token做比对校验,如果校验成功则继续,不成功则拒绝。

    2、源码流程

    class CsrfViewMiddleware(MiddlewareMixin):
    
        def _get_token(self, request):
            if settings.CSRF_USE_SESSIONS:  #默认是False,忽略
                # 省略
                pass    
            else:
                try:
                    cookie_token = request.COOKIES[settings.CSRF_COOKIE_NAME]  #从浏览器中获取cookie中csrf_token的值
                except KeyError:
                    return None
    
                csrf_token = _sanitize_token(cookie_token)  # 对值进行清洗,看是否有效
                if csrf_token != cookie_token:
                    # Cookie token needed to be replaced;
                    # the cookie needs to be reset.
                    request.csrf_cookie_needs_reset = True  # 如果清洗前后的值不一致,则需要重置cookie
                return csrf_token
    
        def process_request(self, request):
            csrf_token = self._get_token(request)
            if csrf_token is not None:
                # Use same token next time.
                request.META['CSRF_COOKIE'] = csrf_token   
    
        def process_view(self, request, callback, callback_args, callback_kwargs):
            if getattr(request, 'csrf_processing_done', False):
                return None 
    
            if getattr(callback, 'csrf_exempt', False):  # 如果视图函数设置了csrf_exempt装饰器,则不进行校验
                return None
    
            if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):  # 如果是这些方法,则不进行校验
                csrf_token = request.META.get('CSRF_COOKIE')  # 否则获取到cookie中csrf_token的值
                if csrf_token is None:
                    return self._reject(request, REASON_NO_CSRF_COOKIE)  # 如果没有这个值则不通过
    
                request_csrf_token = ""
                if request.method == "POST":
                    try:
                        request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')  # 获取页面表单中的值
                    except IOError:
                        pass
    
                if request_csrf_token == "":
                    request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')  # 如果没有,则从请求头中获取
    
                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)  # 如果表单中的值和cookie中的值不一致则拒绝
            return self._accept(request)
  • 相关阅读:
    为了实现一个函数 clone ,可以对 JavaScript 中 5 种主要的数据类型 (包括 Number、 St「ing 、 Object、 A「「ay、 Boolean )进行值(深)复制。
    说说你对语义化的理解
    vue 根据字符串的长度控制显示的字数超出显示省略号
    加密号码将中间四位改为*
    前端项目部署错误:npm ERR! notarget No matching version found for event-stream@3.3.6
    npm报错:A complete log of this run can be fund in:........
    nrm插件的安装插件和使用
    Vue过渡搭配Velocity.js动画的基本使用
    Asp.Net Core&钉钉开发系列
    KnockoutJS知识规整目录
  • 原文地址:https://www.cnblogs.com/yinwenjie/p/10941931.html
Copyright © 2011-2022 走看看