Django:如何像Http404一样引发Http401和Http403异常,引发异常而不是响应

plupiseo  于 2023-03-13  发布在  Go
关注(0)|答案(3)|浏览(180)

我正在尝试使用Django创建一个API,我正在验证请求头是否包含api密钥,并根据该密钥引发异常,如下所示:

def _check_driver_authorization(request):
if request.headers.get('authorization') is not None:
    token = request.headers['authorization']
    user = Driver.objects.filter(access_token=token)
    if user.exists():
        return

    raise Http401
else:
    raise Http403

我没有发现任何人试图这样做,我已经在这里搜索了许多线程,他们都试图返回响应(渲染),我的情况是我试图中断请求并引发异常。

**编辑/更新:**有关详细信息和解释,内置的Http 404异常会引发以下问题:Http404

但是我尝试创建的异常(与Http 404完全相同)引发了以下问题:Http403

fnatzsnv

fnatzsnv1#

有处理程序和异常到响应的转换器,它允许你执行raise Http404。正如你所看到的,它们也将PermissionDenied异常转换为带有403状态代码的响应。所以你可以引发 it 而不是Http403。但是对于401,你必须返回类似return HttpResponse('Unauthorized', status=401)的东西。

i2byvkas

i2byvkas2#

下面是Django处理异常的代码:

def response_for_exception(request, exc):
    if isinstance(exc, Http404):
        if settings.DEBUG:
            response = debug.technical_404_response(request, exc)
        else:
            response = get_exception_response(request, get_resolver(get_urlconf()), 404, exc)

    elif isinstance(exc, PermissionDenied):
        logger.warning(
            'Forbidden (Permission denied): %s', request.path,
            extra={'status_code': 403, 'request': request},
        )
        response = get_exception_response(request, get_resolver(get_urlconf()), 403, exc)

    elif isinstance(exc, MultiPartParserError):
        logger.warning(
            'Bad request (Unable to parse request body): %s', request.path,
            extra={'status_code': 400, 'request': request},
        )
        response = get_exception_response(request, get_resolver(get_urlconf()), 400, exc)

    elif isinstance(exc, SuspiciousOperation):
        if isinstance(exc, (RequestDataTooBig, TooManyFieldsSent)):
            # POST data can't be accessed again, otherwise the original
            # exception would be raised.
            request._mark_post_parse_error()

        # The request logger receives events for any problematic request
        # The security logger receives events for all SuspiciousOperations
        security_logger = logging.getLogger('django.security.%s' % exc.__class__.__name__)
        security_logger.error(
            force_text(exc),
            extra={'status_code': 400, 'request': request},
        )
        if settings.DEBUG:
            response = debug.technical_500_response(request, *sys.exc_info(), status_code=400)
        else:
            response = get_exception_response(request, get_resolver(get_urlconf()), 400, exc)

    elif isinstance(exc, SystemExit):
        # Allow sys.exit() to actually exit. See tickets #1023 and #4701
        raise

    else:
        signals.got_request_exception.send(sender=None, request=request)
        response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())

    # Force a TemplateResponse to be rendered.
    if not getattr(response, 'is_rendered', True) and callable(getattr(response, 'render', None)):
        response = response.render()

    return response

正如你在这里看到的,Django会处理Http404PermissionDenied异常,而Http 401响应似乎没有异常。
PermissionDenied(Http 403)异常为以下异常(类似于Http404异常):

class PermissionDenied(Exception):
    """The user did not have permission to do that"""
    pass

所以它应该可以和raise PermissionDenied一起工作。

**Django文档:**错误视图

kupeojn6

kupeojn63#

您使用的是django rest framework吗?您可以像这样从APIException继承:

from rest_framework.exceptions import APIException

class UnauthorizedException(APIException):
    status_code = 401
    default_detail = "Not logged in"

比如在你的视野里或者任何你想去的地方

if request.user.is_anonymous:
        raise UnauthorizedException

打电话的人会得到401。

相关问题