fuyou_h 2023-06-09 17:49 采纳率: 0%
浏览 17
已结题

Django中间件request.path打印为“/”


class CsrfViewMiddleware(MiddlewareMixin): 
def _reject(self, request, reason):
        logger.warning(
            'Forbidden (%s): %s', reason, request.path,
            extra={
                'status_code': 403,
                'request': request,
            }
        )
        return _get_failure_view()(request, reason=reason)

这里一直报错,打印结果为:
csrf.py WARNING Forbidden (CSRF cookie not set.): /

问题:request.path打印为“/”,无法定位是哪个请求未添加csrf令牌。
已尝试方案:

  1. html中每个post请求后添加{% csrf_token %};
  2. 每个view.py中含post请求的函数前添加 @csrf_exempt;
  3. setting配置中CsrfViewMiddleware在SessionMiddleware之后;
    问题依然没有解决,请问还有其他可尝试的解决方案吗?
  • 写回答

2条回答 默认 最新

  • m0_61558674 2023-06-10 00:29
    关注

    看看能不能解决

    import logging
    
    from django.conf import settings
    from django.http import HttpResponseForbidden
    
    logger = logging.getLogger(__name__)
    
    class CsrfViewMiddleware:
        def __init__(self, get_response):
            self.get_response = get_response
    
        def __call__(self, request):
            response = self.get_response(request)
            return response
    
        def _reject(self, request, reason):
            logger.warning(
                'Forbidden (%s): %s',
                reason,
                request.path,
                extra={
                    'status_code': 403,
                    'request': request
                }
            )
            return HttpResponseForbidden('<h1>禁止访问</h1>')
    
        def process_view(self, request, callback, callback_args, callback_kwargs):
            if getattr(callback, 'csrf_exempt', False):
                return None
    
            if not request.csrf_processing_done:
                # 确保CSRF token存在且正确
                csrf_token = request.POST.get('csrfmiddlewaretoken', '')
                if csrf_token == '':
                    csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
    
                if not self._compare_salted_tokens(csrf_token, request.csrf_token):
                    return self._reject(request, 'CSRF token缺失或不正确')
    
            return None
    
        def _compare_salted_tokens(self, token1, token2):
            """
            将两个token通过加盐哈希算法进行比较。
            """
            from django.utils.crypto import constant_time_compare
            from django.utils.six.moves import range
            for salt in getattr(settings, 'CSRF_SALT', ()):
                expected_token = _salt_cipher_secret(token1 + salt)
                actual_token = _salt_cipher_secret(token2 + salt)
                if constant_time_compare(expected_token.encode(), actual_token.encode()):
                    return True
            return False
    
    def _salt_cipher_secret(secret):
        """
        为secret添加一个salt,以便相同的secret在不同的进程中生成不同的哈希值。
        """
        from django.utils.crypto import get_random_string
        return get_random_string(7, 'abcdefghijklmnopqrstuvwxyz') + secret
    
    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 6月16日
  • 创建了问题 6月9日