DRF 总是返回“未提供身份验证凭据”

Posted

技术标签:

【中文标题】DRF 总是返回“未提供身份验证凭据”【英文标题】:DRF always returning "Authentication credentials were not provided" 【发布时间】:2016-03-17 09:03:36 【问题描述】:

更新:从 nginx 配置中删除了 set_header 令牌。意识到这对问题没有帮助。我觉得问题在于 Django 没有获得正确的标头,并且它们在某个地方“丢失”了。

我正在尝试为一个秘密圣诞老人项目创建一个 REST api。我已将其设置为必须先对用户进行身份验证,然后才能进行某些调用。这在我的本地机器上运行良好,但在任何地方托管时似乎都不起作用。

我已经在 Heroku 和 ubuntu 服务器上尝试过。但是,我更愿意让它在 Ubuntu 服务器上运行。我正在使用 gunicorn 和 nginx 为应用程序提供服务,但在所有需要身份验证的调用中,我都收到“未提供身份验证凭据”。我正在使用 TokenAuthentication 并在 Authorization 标头中使用前缀 Token 传递我的令牌。

非常感谢任何帮助。

settings.py

REST_FRAMEWORK = 
    'PAGINATE_BY': 30,
    'PAGINATE_BY_PARAM': 'per_page',
    'MAX_PAGINATE_BY': 1000,
    "DATETIME_FORMAT": "%Y-%m-%dT%H:%M:%S%z",
    'DEFAULT_RENDERER_CLASSES': (
        'rest_framework.renderers.JSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),

views.py

class RoomViewSet(mixins.RetrieveModelMixin,
              viewsets.GenericViewSet):
"""
Creates, Updates, and retrives Rooms
"""

queryset = Room.objects.all()
serializer_class = RoomSerializer
permission_classes = (IsAuthenticated, )
lookup_field = 'slug'

gunicorn.conf

description "Gunicorn application server handling myproject"

start on runlevel [2345]
stop on runlevel [!2345]

respawn
setuid dannywilson
setgid www-data
chdir /storage/sites/secret_santa/

exec santa/bin/gunicorn --pythonpath="$PWD/secret_santa" --bind=unix:"$PWD/secret_santa/gunicorn.sock" wsgi:application

nginx 配置

upstream test_server 
    server unix:/storage/sites/secret_santa/secret_santa/gunicorn.sock;


server 
    listen 80;
    server_name webaddress;

    access_log /storage/sites/_logs/secret_santa_api/nginx-access.log;
    error_log /storage/sites/_logs/secret_santa_api/nginx-error.log;

    location / 

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_ignore_headers Cache-Control Expires Pragma;

        if (!-f $request_filename) 
            proxy_pass http://test_server;
            break;
        

    

【问题讨论】:

您发送的具体标头是什么? 只是一个带有 Token 的 Authorization 标头 你给标题起什么名字? 授权,因为这是在 localhost 上起作用的。 尝试发送 WWW-Authenticate 【参考方案1】:

这里有两件事让我印象深刻:

"proxy_set_header 令牌 $http_token;"但我认为 $http_token 没有定义。 对标头使用“令牌”而不是“授权”。 Documentation 提到“为了让客户端进行身份验证,令牌密钥应包含在 Authorization HTTP 标头中。”

【讨论】:

【参考方案2】:

这可能会对您有所帮助 (from django rest framework documentation):

注意,如果使用 mod_wsgi 部署到 Apache,授权 默认情况下,标头不会传递给 WSGI 应用程序,因为它 假定身份验证将由 Apache 处理,而不是 在应用程序级别。

如果您要部署到 Apache,并使用任何非基于会话的 身份验证,您将需要显式配置 mod_wsgi 以通过 所需的标头到应用程序。这可以通过 在适当的地方指定 WSGIPassAuthorization 指令 上下文并将其设置为“开”。

# this can go in either server config, virtual host, directory or .htaccess
WSGIPassAuthorization On

【讨论】:

我们都可以访问文档,如果您要参考文档,您至少应该在答案中包含解决此特定问题的特定部分。【参考方案3】:

因为下面的配置:

REST_FRAMEWORK = 
........
'DEFAULT_PERMISSION_CLASSES': [
    'rest_framework.permissions.IsAuthenticated',],
'DEFAULT_AUTHENTICATION_CLASSES': (
    'rest_framework.authentication.TokenAuthentication',),

如果您不需要验证,请删除这两个配置,否则如果您想使用TokenAuthentication,则需要将rest_framework.authtoken 添加到已安装的应用程序中:

INSTALLED_APPS = (
...
'rest_framework.authtoken'
)

然后按照TokenAuthentication中的说明进行操作

【讨论】:

我已安装的应用程序中有 rest_framework.authtoken。我的问题是,当我的任何 API 调用不在本地测试服务器上时,我无法对其进行身份验证。 因此,如果它在您的本地服务器而不是远程服务器上运行良好,您可能会发现这里的解决方案很有帮助check here

以上是关于DRF 总是返回“未提供身份验证凭据”的主要内容,如果未能解决你的问题,请参考以下文章

未提供身份验证凭据 drf

DRF:“详细信息”:“未提供身份验证凭据。”

Django Rest Framework JWT 未提供身份验证凭据

POST 请求的身份验证错误:“未提供身份验证凭据”使用 Axios,但使用 POSTMAN 工作

djangorestframework-jwt 未提供身份验证凭据

未提供 Angular + Django REST 身份验证凭据