【问题标题】:Django prints error when PermissionDenied exception raises当 PermissionDenied 异常引发时 Django 打印错误
【发布时间】:2021-10-14 14:29:16
【问题描述】:

在我们的项目中,我们使用了 django SessionMiddleware 来处理用户会话,并且运行良好。这里唯一的问题是当PermissionDenied 异常发生时,错误及其回溯将在控制台中打印出来!然而正如预期的那样,通过引发该异常,403 页面将显示给用户,但我认为这似乎不合理,因为这里的中间件正在处理异常!就像未发现异常一样,我希望控制台中没有错误。有什么问题吗?!

这里是中间件设置:

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django_otp.middleware.OTPMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'axes.middleware.AxesMiddleware',
]

这是打印的错误:

Forbidden (Permission denied): /the/not_allowed/page
Traceback (most recent call last):
  File "/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
    response = get_response(request)
  File "/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/lib/python3.8/contextlib.py", line 75, in inner
    return func(*args, **kwds)
  File "/our_project/base/decorators.py", line 88, in wrapper
    return view_func(request, *args, **kwargs)
  File "/venv/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/venv/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 20, in _wrapped_view
    if test_func(request.user):
  File "/venv/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 70, in check_perms
    raise PermissionDenied
django.core.exceptions.PermissionDenied

【问题讨论】:

  • 您能否提供引发此错误的代码?
  • @AyushGupta 在此示例中,异常是从django.contrib.auth.decorators 中的permission_required 装饰器引发的。我将 'raise_exception=True` 传递给此装饰器以使其引发异常,而不是重定向到登录页面。
  • 为什么不创建一个禁止页面模板而不是引发异常将它们发送到禁止页面模板?
  • @AyushGupta 我们确实有一个禁止页面,但是会话中间件负责将用户重定向到该页面(正如它正在做的那样),就像处理 404 错误一样。但是,在这种情况下,我们必须编写另一个装饰器来检查权限,而不是使用 django 本身提供的 permission_requiered 装饰器。 :)
  • 您有自定义的handler403 吗?尝试在您的一个模板中创建一个空的403.html

标签: python django django-middleware django-sessions


【解决方案1】:

来自comment

在此示例中,异常是从 permission_required 引发的 django.contrib.auth.decorators 中的装饰器。我通过了 raise_exception=True 到此装饰器,使其引发异常而不是重定向到登录页面

所以,很明显你已经在你的装饰器中设置了 raise_exception=True

来自doc

如果给出raise_exception参数,装饰器会引发PermissionDenied,提示403(HTTP Forbidden)视图,而不是重定向到登录页面。

所以,从技术上讲,当条件不满足时,Django 会引发异常。但是,根据 403.html 的值,Django 会显示普通 403 页面自定义 HTML 响应


我希望控制台中没有错误。有什么问题吗?

这里没有错(或者我什么都看不到)。

所以,如果你想从控制台省略回溯,你可能需要编写一个错误处理中间件来处理这个异常。

# error handling middleware
from django.core.exceptions import PermissionDenied
from django.shortcuts import render


class PermissionDeniedErrorHandler:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        return response

    def process_exception(self, request, exception):
        # This is the method that responsible for the safe-exception handling
        if isinstance(exception, PermissionDenied):
            return render(
                request=request,
                template_name="your_custom_403.html",
                status=403
            )
        return None

注意:不要忘记在您的MIDDLEWARE设置中绑定此中间件。

因此,您不会在控制台中获得任何错误回溯。

干杯!!!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    相关资源
    最近更新 更多