【问题标题】:Django: How to raise Http401 and Http403 exceptions like Http404, RAISE EXCEPTION not RESPONSEDjango:如何引发 Http401 和 Http403 异常,如 Http404、RAISE EXCEPTION not RESPONSE
【发布时间】:2019-11-19 11:36:18
【问题描述】:

我正在尝试使用 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

我没有发现任何人试图这样做,并且我在这里搜索了很多线程,他们都试图返回响应(渲染),我的情况是我试图中断请求并提出例外。 我的灵感来自 get_object_or_404。

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

但我试图制造的异常(与 Http404 完全相同)引发了以下问题: Http403

【问题讨论】:

  • 你得到的错误是什么?
  • @luis.parravicini 没有错误,它要求我创建类Http401Http403,因为我受到Http404 的启发,当我查看代码时,它包含什么都没有……

标签: python django exception


【解决方案1】:

handler 和响应converter 的例外情况,它允许您执行raise Http404。如您所见,他们还将PermissionDenied 异常转换为带有 403 状态代码的响应。所以你可以提出 it 而不是 Http403。但是对于 401,你必须返回 return HttpResponse('Unauthorized', status=401) 类似的东西。

【讨论】:

    【解决方案2】:

    这是处理异常的一段 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 文档: Error views

    【讨论】:

    • 它适用于 raise PermissionDenied,但在这种情况下,如果我想记录这些事情,我不知道用户是否提供了错误的密钥,或者根本没有提供...... . 为了安全起见,我想知道这样的事情......
    • 如果您在代码中输入raise something,我知道您应该知道这段代码在什么条件下执行。
    猜你喜欢
    • 2015-06-25
    • 2021-07-05
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    • 2020-06-20
    • 2011-12-04
    • 1970-01-01
    相关资源
    最近更新 更多