【问题标题】:How do I return a 401 Unauthorized in Django?如何在 Django 中返回 401 Unauthorized?
【发布时间】:2011-05-20 09:38:22
【问题描述】:

不要这样做:

res = HttpResponse("Unauthorized")
res.status_code = 401
return res

有没有办法不用每次都输入?

【问题讨论】:

    标签: python django


    【解决方案1】:

    继承解决方案

    from django.http import HttpResponse
    
    class Http401(HttpResponse):
        def __init__(self):
            super().__init__('401 Unauthorized', status=401)
    

    util.py 中替换多个调用:

    return HttpResponse('401 Unauthorized', status=401)
    

    只需:

    return Http401()
    

    有趣的是,1.9.6 https://github.com/django/django/blob/1.9.6/django/http/response.py#L443 中还有其他命名响应,但 401 没有。

    【讨论】:

    • 我喜欢这个回复。但是__init__(self): 的行应该像这样改变super(Http401, self).__init__(message, status=401)
    • @Hobaak 在 Python 3 中,我们可以只写 super().__init__: stackoverflow.com/a/33191175/895245 。可以添加message,但如果您不使用 API,仅使用 HTTP 浏览器端点,则不是很有必要。
    • 好的。该解决方案在 1.8.6 Django 和 2.7 Python 中给我带来了错误。我的建议帮助解决了这个问题。也许它适用于 Python 3。不过,在这些答案中,我最喜欢这个解决方案。
    • 如果您希望在响应 401 时满足包含该标头的要求,可以添加到 __init__ 的末尾:self['WWW-Authenticate'] = 'FormBased'
    【解决方案2】:
    class HttpResponseUnauthorized(HttpResponse):
        status_code = 401
    
    ...
    return HttpResponseUnauthorized()
    

    通常,您应该在__init__ 中设置实例,否则您最终会得到在所有实例之间共享的类变量。但是,Django 已经为您做到了:

    class HttpResponse(object):
        """A basic HTTP response, with content and dictionary-accessed headers."""
    
        status_code = 200
    
        def __init__(self, content='', mimetype=None, status=None,
                content_type=None):
            # snip...
            if status:
                self.status_code = status
    

    (see the Django code in context)

    【讨论】:

      【解决方案3】:

      我知道这是一个旧的,但它是“django 401”的最佳 Google 结果,所以我想我会指出这一点......

      假设您已经导入了django.http.HttpResponse,您可以在一行中完成:

      return HttpResponse('Unauthorized', status=401)
      

      'Unauthorized' 字符串是可选的。很简单。

      【讨论】:

      • 这是可以通过的,我赞成;但是 - 对于类似的情况,我会考虑使用错误 403(禁止) - 因为有一个现成的机制:docs.djangoproject.com/en/dev/topics/http/views/… - 只需在根 urls.py 中定义 handler403,然后在 raise django.core.exceptions.PermissionDenied 中定义。
      • @TomaszGandor 是的,或者return HttpResponseForbidden 也适用于 403(提出一个例外,因为你建议它通常更方便)。 401 和 403 并不完全相同,尽管有些人争论确切的区别。
      • 根据 Wikipedia,401 响应必须包含 WWW-Authenticate 标头字段。所以,使用 403 更简单。en.wikipedia.org/wiki/List_of_HTTP_status_codes
      • @SimonSteinberger 非常正确,但没有标准的 WWW-Authenticate 标头,任何系统都无法识别当今大多数身份验证系统,因此除非您使用基本身份验证,否则我认为这是一个违反规范的务实案例。 IMO 403 有一个单独的目的(即您已通过身份验证,但您无权访问此 [403] 与您尚未通过身份验证 [401])
      • 我想不出没有 API 的 401 用例,所以如果有人有想法的话.. 像 drf 这样的 API 框架通常包含一个 401:django-rest-framework.org/api-guide/exceptions
      【解决方案4】:
      class HttpResponseUnauthorized(HttpResponse):
          def __init__(self):
              self.status_code = 401
      
      ...
      return HttpResponseUnauthorized()
      

      【讨论】:

      • 不需要放在__init__方法中,在类定义中设置属性即可。
      • @Matthew:我一般不会那样做。太容易掉入无意共享对象的陷阱,并且不清楚在类主体中放置一些初始化,在__init__中放置一些。
      • 这会返回以下错误:'HttpResponseUnauthorized' object has no attribute '_headers'
      • 从查看 django.http.__init__.py 将其添加到类定义中似乎是首选方法,如果您希望在 中执行此操作,应通过 super 调用 HttpRepsonses 构造函数初始化
      • 抛出对象没有属性'_headers'
      【解决方案5】:

      编写一个视图装饰器,检查相应的 HTTP 标头并返回相应的响应(响应代码 401 没有 built-in type)。

      【讨论】:

        猜你喜欢
        • 2015-03-13
        • 2021-09-02
        • 2021-10-19
        • 2013-04-05
        • 1970-01-01
        • 1970-01-01
        • 2022-01-11
        • 2020-02-09
        • 2021-10-11
        相关资源
        最近更新 更多