django rest框架在nginx后面但不直接给出403

Posted

技术标签:

【中文标题】django rest框架在nginx后面但不直接给出403【英文标题】:django rest framework gives 403 when behind nginx but not directly 【发布时间】:2013-04-05 04:50:48 【问题描述】:

使用 django-rest-framework。在 nginx 后面的生产环境中运行时出现 HTTP 403 错误。当我调用从 APIView 继承以支持 GET 操作的特定视图时,我得到:

"detail": "Invalid username/password"

但是...我只在浏览器中得到这个。当我对同一个 URL 使用 curl 时,我不明白。无论是在 Chrome 和 Firefox 中直接点击 URL,还是通过 AJAX 加载 URL,我都会收到此错误。

如果我先使用管理员帐户通过 Django Admin 登录,我不会收到错误消息。

另外,我只知道这是我从 nginx 后面运行的。如果我使用 Django 开发服务器或 gunicorn 运行,并直接点击端口,我很好,并且可以愉快地匿名点击 URL。如果我把 nginx 放在前面,转发到同一个 gunicorn/runserver 我得到这个错误。

也许这与我的 nginx proxy_pass 设置有关?

location / 
    proxy_pass http://127.0.0.1:8000;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

我正在运行 django rest 框架 2.2.6、Django 1.5 和 nginx 1.2.7。

我在 rest 框架中将限制设置为一个愚蠢的高数字,并查看了默认情况下似乎都打开的权限(但也设置得如此明确)。

谁能指出我正确的方向?

谢谢!

卢多。

【问题讨论】:

您对 django-rest-framework 的身份验证设置是什么? 我只是使用默认值,看起来很合适。 【参考方案1】:

当您向网站发送请求时,在基本身份验证之后, 客户端(浏览器)发送“授权”标头(应该 - 请参阅:***上的“基本访问身份验证”)。

Ngnix 将其传递给您的应用程序。

Django Rest Framework 还支持:BasicAuthentication,默认开启。

REST_FRAMEWORK = 
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    )

来源:http://www.django-rest-framework.org/api-guide/authentication/

所以 django-rest-framework 看到 'Authorization' 标头,并认为应该是 django 用户的密码。

如果这样的用户不存在,那么你得到:“HTTP 401 Unauthorized”。 见:http://www.django-rest-framework.org/api-guide/authentication/#basicauthentication

解决方案

选择一个: a) 添加到您的 ngnix 站点配置中

location / 
    ...
    proxy_set_header    Authorization    "";
    ...

所以 DRF 不会得到 'Authorization' 标头,所以它不会尝试匹配 django 用户。

在此更改之后 - 无法在 django 端使用基本身份验证(空头!

b) 从 REST_FRAMEWORK 中删除“rest_framework.authentication.BasicAuthentication”(在您的 django 设置中)。

如果未定义,请添加到您的 django 设置中:

REST_FRAMEWORK = 
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.SessionAuthentication',
    )

可能是最好的解决方案。

c) 使用您的 django 用户/密码进行基本身份验证?

真的吗? - 不要!

【讨论】:

【参考方案2】:

如果它是基本的 http 身份验证(如 @Sjoerd 的情况)并且您不需要 django 身份验证,您还可以在 nginx 反向代理配置中删除 Authorization 标头:

location / 
    ...
    proxy_set_header   Authorization    "";

【讨论】:

谢谢!我们刚刚遇到了同样的问题,这有帮助!【参考方案3】:

在我的例子中,我在 Apache 中配置了 HTTP 基本身份验证,但在我的 Django 项目中没有。因为请求具有身份验证标头,所以 Django 应用程序认为我想使用它进行身份验证。我使用以下设置禁用了 Django REST 框架中的身份验证:

REST_FRAMEWORK = 
    'DEFAULT_AUTHENTICATION_CLASSES': []

【讨论】:

谢谢!这正是我的问题 您不需要禁用所有身份验证类,只需删除基本身份验证。在此处查看另一个答案***.com/questions/19693433/… 优秀。这是我使用 VPS + Apache + Passenger (Dreamhost) 时遇到的问题。【参考方案4】:

如果您启用了限制,您将收到 403 FORBIDDEN。基于这个问题:https://github.com/tomchristie/django-rest-framework/issues/667,关闭 request.user/request.auth 的惰性评估可能是最好的做法。

【讨论】:

更新到最新版本的 REST 框架应该可以解决这个问题。 (引用的票现已关闭) 嗨。谢谢!不过,我在 2.2.6 上,看起来它包含此修复程序。我正在尝试关注该线程,但看不到禁用节流的简单方法。我确实设置了一个非常高的油门值。也许我应该尝试自定义身份验证类?除非我听到其他情况,否则我想接下来我会尝试。谢谢 我关闭了节流和身份验证,一切都开始工作了。谢谢。

以上是关于django rest框架在nginx后面但不直接给出403的主要内容,如果未能解决你的问题,请参考以下文章

我们如何使用基于函数的视图在 django rest 框架中发布数据?

带有 CSRF/CORS 的带有 TokenAuthentication 的 Django REST 框架

HTTP基本身份验证背后的Django Rest框架

带有 CSRF/CORS 的带有 TokenAuthentication 的 Django REST 框架

在 django rest 框架中更新 JSONField

django+vue前后端分离项目部署