Nginx+Django应用过多重定向问题求助(HTTP转HTTPS)
解决Nginx+Django遗留代码的HTTPS重定向循环问题
环境信息
- Nginx版本:1.2.1
- Django版本:1.11
- Nginx配置存放路径:
sites-enabled目录
问题描述
配置Nginx与SSL证书后出现过多重定向错误,需求是实现http://mysite.com自动跳转至https://mysite.com。
当前配置
Nginx配置(corpmanage.conf)
# corpmanage.conf # the upstream component nginx needs to connect to upstream django { server unix:/home/corpmanage/corpmanage.sock; # for a file socket # server 127.0.0.1:8001; # for a web port socket (we'll use this first) } # configuration of the server server { listen 80; server_name mysite.com; server_name www.mysite.com; client_max_body_size 30m; # Django media location /media { alias /home/corpmanage/mediafiles; # your Django project's media files - amend as required } location /static { alias /home/corpmanage/static-prod; # your Django project's static files - amend as required } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass django; include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed uwsgi_read_timeout 600; } } server { # the port your site will be served on listen 443 ssl; # the domain name it will serve for server_name mystic.com; server_name www.mysite.com; root /home/corpmanage; charset utf-8; # max upload size client_max_body_size 30m; ssl on; ssl_certificate /root/.acme.sh/mystite.com/fullchain.cer; ssl_certificate_key /root/.acme.sh/mysite.com/mysite.comkey; # Django media location /media { alias /home/corpmanage/mediafiles; # your Django project's media files - amend as required } location /static { alias /home/corpmanage/static-prod; # your Django project's static files - amend as required } # Finally, send all non-media requests to the Django server. location / { uwsgi_pass django; include /etc/nginx/uwsgi_params; # the uwsgi_params file you installed uwsgi_read_timeout 600; } }
Django配置
SECURE_CONTENT_TYPE_NOSNIFF = True SECURE_SSL_REDIRECT = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') SECURE_BROWSER_XSS_FILTER = True SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True CSRF_COOKIE_HTTPONLY = True X_FRAME_OPTIONS = 'DENY'
问题根源
- 域名拼写错误:443端口的
server_name写成了mystic.com,证书路径里的mystite.com也是拼写错误,导致HTTPS请求无法正确匹配对应server块。 - 80端口处理不当:未直接将HTTP请求重定向至HTTPS,而是转发给Django,结合
SECURE_SSL_REDIRECT=True会触发二次重定向。 - 缺少HTTPS头传递:Nginx未向Django传递
X-Forwarded-Proto头,导致Django无法识别当前请求为HTTPS,即使是HTTPS请求也会被强制重定向,形成循环。
解决方案
修正后的Nginx配置
# corpmanage.conf upstream django { server unix:/home/corpmanage/corpmanage.sock; } # HTTP请求直接重定向到HTTPS server { listen 80; server_name mysite.com www.mysite.com; # 所有HTTP请求永久重定向到HTTPS return 301 https://$server_name$request_uri; } # HTTPS服务配置 server { listen 443 ssl; server_name mysite.com www.mysite.com; root /home/corpmanage; charset utf-8; client_max_body_size 30m; ssl on; ssl_certificate /root/.acme.sh/mysite.com/fullchain.cer; ssl_certificate_key /root/.acme.sh/mysite.com/mysite.com.key; # 修正证书文件名格式 # 静态资源直接返回 location /media { alias /home/corpmanage/mediafiles; } location /static { alias /home/corpmanage/static-prod; } # 动态请求转发给Django,并传递HTTPS标识头 location / { uwsgi_pass django; include /etc/nginx/uwsgi_params; uwsgi_read_timeout 600; # 明确传递HTTPS协议头给Django uwsgi_param HTTP_X_FORWARDED_PROTO https; } }
操作步骤
- 将上述修正后的配置替换原
corpmanage.conf文件。 - 检查证书文件名是否正确(原配置中
mysite.comkey应为mysite.com.key,需根据实际文件调整)。 - 重启Nginx服务:
/etc/init.d/nginx restart - 验证Django的
SECURE_PROXY_SSL_HEADER配置保持不变(已正确设置为('HTTP_X_FORWARDED_PROTO', 'https'))。
原理说明
- 80端口的server块直接返回301重定向,避免请求进入Django触发二次重定向。
- 修正域名和证书路径,确保HTTPS请求能正确匹配到对应server块。
- 通过
uwsgi_param HTTP_X_FORWARDED_PROTO https;向Django传递协议信息,让Django识别当前请求为HTTPS,不再触发强制重定向,打破循环。
内容的提问来源于stack exchange,提问作者Rasuljon Kurbanov
相关产品推荐
相关产品推荐

