【问题标题】:How to specify explicit host name in Django settings?如何在 Django 设置中指定显式主机名?
【发布时间】:2020-05-09 01:59:05
【问题描述】:

我正在开发一个通过多个 Docker 容器运行的 Django 项目,而 Django 站点本身就是一个 Nginx 容器将请求转发到的中间件。为了测试 Nginx 容器的 80 端口映射到 8080。因此我去http://localhost:8080/ 并查看 Django 网站。

我遇到了重定向 URL(由用于 Google 登录的 social-auth-app-django 包构建)使用 http://localhost 而不是 http://localhost:8080 作为基础的问题。

LOGIN_REDIRECT_URL 设置不是我想要的,因为它发生在身份验证成功之后。

我尝试了SOCIAL_AUTH_LOGIN_REDIRECT_URL,它是mentioned somewhere,但那是旧版本,似乎不再有任何作用。

既然 Django 对所有绝对 URL 使用 build_absolute_uri,那么一定有办法覆盖基本 URL 和/或主机?

【问题讨论】:

  • 重定向是发生在 Nginx 级别还是 django 级别?
  • @MattSeymour - 在 Django 级别作为social-auth-app-django 包的一部分。有时间我会深入研究源代码。我确定这是我问错的常见问题
  • @solarissmoke - 类似的问题,但有相反的问题:我想 add 端口 (8080) 而不是将其剥离。但是,我可以在 Nginx 中做一些事情来传递收到的端口号。感谢您的链接;我会尝试一些。

标签: django python-social-auth django-socialauth


【解决方案1】:

TL;DR = Nginx 没有 Docker 映射端口的概念,需要对它们进行硬编码。

类似问题:https://serverfault.com/questions/577370/how-can-i-use-environment-variables-in-nginx-conf

Django 要求 HTTP 请求标头包含主机所需的信息(下面的代码 sn-p)。这种情况下需要从 Nginx 传入:

location / {
    proxy_pass http://web:7000;
    proxy_set_header Host $host:8080;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

请注意端口的不幸硬编码:$host:8080。 “外部”问题是 Nginx 容器的端口使用 Docker 映射到 8080 (-p 80:8080),因此它不知道它实际上是在端口 8080 上运行; Nginx 检测到自己在 80 端口上运行。

一个 SOCIAL_AUTH_LOGIN_REDIRECT_URL 的 Django 设置,但像这样指定它:

SOCIAL_AUTH_LOGIN_REDIRECT_URL = 'http://localhost:8080/complete/google-oauth2/'

在尝试通过 Google 进行身份验证时导致这种情况发生:

AuthMissingParameter at /complete/google-oauth2/

缺少所需的参数状态

请求方法:GET

请求网址:http://localhost:8080/complete/google-oauth2/

Django 版本:2.1.5

异常类型:AuthMissingParameter

异常值:

缺少所需的参数状态

异常位置:/usr/local/lib/python3.6/site-packages/social_core/backends/oauth.py 在 validate_state,第 88 行

Python 可执行文件:/usr/local/bin/python

Python 版本:3.6.10

因此,我目前唯一的解决方案是在构建 Docker 映像时将端口烘焙到 Nginx 配置中。

Django 2.1.5 版本获取主机代码:

def _get_raw_host(self):
    """
    Return the HTTP host using the environment or request headers. Skip
    allowed hosts protection, so may return an insecure host.
    """
    # We try three options, in order of decreasing preference.
    if settings.USE_X_FORWARDED_HOST and (
            'HTTP_X_FORWARDED_HOST' in self.META):
        host = self.META['HTTP_X_FORWARDED_HOST']
    elif 'HTTP_HOST' in self.META:
        host = self.META['HTTP_HOST']
    else:
        # Reconstruct the host using the algorithm from PEP 333.
        host = self.META['SERVER_NAME']
        server_port = self.get_port()
        if server_port != ('443' if self.is_secure() else '80'):
            host = '%s:%s' % (host, server_port)
    return host

【讨论】:

猜你喜欢
  • 2015-11-08
  • 2019-02-14
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 2022-06-15
  • 2011-05-11
  • 2011-08-11
  • 2020-10-12
相关资源
最近更新 更多