解决Django应用部署时激活链接缺少端口号的问题

引言

在当今技术迅速发展的时代,前后端分离已经成为现代Web开发的一项标准实践。然而,当我们将这些先进的架构部署到生产环境时,常常会遇到一些预料之外的挑战。

问题说明

在一个典型的例子中,我在Windows环境下开发了一个采用Django和Vue进行前后端分离的项目,并顺利完成了调试。随后,我开始在Linux CentOS环境上进行部署。我的项目使用了Django的Djoser库来实现注册功能,其中包括向注册邮箱发送激活链接的功能。然而,在部署过程中,我遇到了一个问题:发送到注册邮箱的激活链接缺少了端口号。

项目现状

我的Django项目的settings.py文件中关于Djoser的配置如下所示:

DJOSER = {
    'USER_ID_FIELD': 'username',
    'LOGIN_FIELD': 'email',
    'SEND_ACTIVATION_EMAIL': True,
    'ACTIVATION_URL': 'activate/{uid}/{token}',
    'SEND_CONFIRMATION_EMAIL': True,
    'PASSWORD_RESET_CONFIRM_URL': 'password_reset/{uid}/{token}',
    'PASSWORD_RESET_CONFIRM_RETYPE': True,
    'PASSWORD_RESET_SHOW_EMAIL_NOT_FOUND': True,
    'SET_PASSWORD_RETYPE': True,
    'SERIALIZERS': {
        "user_create": "account.serializers.CustomUserCreateSerializer",
        "current_user": "account.serializers.CustomUserSerializer",
    }
}

我还配置了Nginx来反向代理Django应用,具体的Nginx配置如下:

location /api/ {
    proxy_pass http://backend/api/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

分析原因

问题的根本原因在于,通过Nginx反向代理访问Django应用时,Django未能接收到原始请求中的端口信息。这是因为Nginx代理默认不转发原始请求的端口信息给上游应用。Django在生成完整URL时,依赖于接收到的请求信息。

问题解决

为了解决这个问题,我在Django项目的settings.py文件中做了如下配置:

# 使用X-Forwarded-Host头部,这个头部会包含原始的主机名和端口号
USE_X_FORWARDED_HOST = True

# 当Django运行在HTTPS之后的反向代理后面时,告诉Django使用`X-Forwarded-Proto`头部识别协议
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

启用了USE_X_FORWARDED_HOST,允许Django使用X-Forwarded-Host头部,该头部包含了原始的主机名和端口号。
设置了SECURE_PROXY_SSL_HEADER为(‘HTTP_X_FORWARDED_PROTO’, ‘https’),当Django运行在HTTPS协议的反向代理后时,这告诉Django使用X-Forwarded-Proto头部来识别协议。
同时,我更新了Nginx的配置,增加了proxy_set_header X-Forwarded-Host h o s t : host: host:server_port;,确保Nginx将主机名和端口号通过X-Forwarded-Host头传递给Django应用:

location /api/ {
    proxy_pass http://backend/api/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $host:$server_port;
}

通过这些调整,我成功解决了激活链接缺少端口号的问题。这一经历再次强调了,无论技术多么先进,深入理解其背后的原理和细节始终是成功部署和维护项目的关键。我希望这篇文章能够帮助你在自己的项目中避免遇到类似的问题,并鼓励你探索技术的更多奥秘。

你可能感兴趣的:(Python,web,django,sqlite,python)