• 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)
  • 相关阅读:
    (七)android开发中两种方式监听短信的原理和实现
    (三)android中Toast的使用
    (二)、Android ListView滑动过程中图片显示重复错位闪烁问题解决
    (一)PagerAdapter、FragmentPagerAdapter、FragmentStatePagerAdapter的区别
    (六)Android中使用CountDownTimer实现倒计时功能
    (五)在android 4.4上设置手机状态栏的背景
    (四)使用PagerSlidingTabStrip和ViewPager实现可左右滑动和点击效果功能
    devexpress表格gridcontrol实现列统计,总计,平均,求和等。
    常用GDB命令行调试命令
    新浪微博SSO授权后回调客户端没有执行sinaweiboDidLogIn&无法返回应用
  • 原文地址:https://www.cnblogs.com/yinwenjie/p/10941931.html
Copyright © 2020-2023  润新知