• CSRF Failed: Referer checking failed no Referer


    postman模拟登录出了这个错误,其实看标题就知道大概是怎么回事,网上大概找了办法,也没说到位,所以干脆自己找源码了.

    问题很明显就是出在 CSRF 上,理所当然去查看 CsrfViewMiddleware 中间件:

     1 class CsrfViewMiddleware(object):
     2 
     3     def _accept(self, request):
     4        
     5         request.csrf_processing_done = True
     6         return None
     7 
     8     def _reject(self, request, reason):
     9         logger.warning('Forbidden (%s): %s', reason, request.path,
    10             extra={
    11                 'status_code': 403,
    12                 'request': request,
    13             }
    14         )
    15         return _get_failure_view()(request, reason=reason)
    16 
    17     def process_view(self, request, callback, callback_args, callback_kwargs):
    18 
    19         if getattr(request, 'csrf_processing_done', False):
    20             return None
    21 
    22         try:
    23             csrf_token = _sanitize_token(
    24                 request.COOKIES[settings.CSRF_COOKIE_NAME])
    25             request.META['CSRF_COOKIE'] = csrf_token
    26         except KeyError:
    27             csrf_token = None
    28            
    29             request.META["CSRF_COOKIE"] = _get_new_csrf_key()
    30         
    31             return None
    32 e that anything not defined as 'safe' by RFC2616 needs protection
    33         if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
    34             if getattr(request, '_dont_enforce_csrf_checks', False):
    35                 return self._accept(request)
    36 
    37             if request.is_secure():
    38                 referer = force_text(
    39                     request.META.get('HTTP_REFERER'),
    40                     strings_only=True,
    41                     errors='replace'
    42                 )
    43                 if referer is None:
    44                     return self._reject(request, REASON_NO_REFERER)      # 问题就出在这里  
    45 
    46                 good_referer = 'https://%s/' % request.get_host()
    47                 if not same_origin(referer, good_referer):
    48                     reason = REASON_BAD_REFERER % (referer, good_referer)
    49                     return self._reject(request, reason)
    50 
    51             if csrf_token is None:
    52                 return self._reject(request, REASON_NO_CSRF_COOKIE)
    53             request_csrf_token = ""
    54             if request.method == "POST":
    55                 try:
    56                     request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
    57                 except IOError:
    58                     pass
    59 
    60             if request_csrf_token == "":
    61                 request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
    62 
    63             if not constant_time_compare(request_csrf_token, csrf_token):
    64                 return self._reject(request, REASON_BAD_TOKEN)
    65 
    66         return self._accept(request)

    首先在文件里面搜索报错的信息字符串,找到这个:

    REASON_NO_REFERER = "Referer checking failed - no Referer."

    然后搜索 REASON_NO_REFERER 就会找到上面的那一段代码中出错的位置.(为什么写这些东西,因为我有个同学就是从来都不会找出错原因,方法有时候比结论更重要)

    然后代码里面说的很清楚了, referer = request.META.get('HTTP_REFERER') 

    这就说明请求头里面没有 REFERER这个信息,都知道的,Django会把自定义的请求头大写并在前面添加 HTTP_ ,所以在postman的header里面添加这个 referer 字段就好了.

    注意,referer的格式是 https://www.domain.com/.          后面有个点

    然后就OK了

    多说两句,看看人家django多贴心,如果是post请求的话,会尝试从两个地方获取csrftoken,请求体里面可以放,就算忘了放,还会从请求头里面拿(54行 - 64行)

  • 相关阅读:
    exec
    eval
    Python--day23--类的命名空间
    Python--day23--初识面向对象复习
    Python--day22--面向对象的交互
    Python--day21--异常处理
    Python--day21--包
    Python--day21--复习
    Python--day20--模块的导入
    动态加载布局的技巧
  • 原文地址:https://www.cnblogs.com/haiton/p/10715120.html
Copyright © 2020-2023  润新知