Django重置密码视图中protocol返回http而非https问题排查
Django密码重置邮件中
protocol返回http而非https的问题排查 问题场景
我在基于django/postgresql/docker的应用中使用Django registration模块,重写了密码重置视图:
class ResetPasswordView(SuccessMessageMixin, PasswordResetView): template_name = 'registration/password_reset_form.html' email_template_name = 'registration/password_reset_email.html' subject_template_name = 'registration/password_reset_subject.txt' success_message = "We've emailed you instructions for setting your password, " \ "if an account exists with the email you entered. You should receive them shortly." \ " If you don't receive an email, " \ "please make sure you've entered the address you registered with, and check your spam folder." success_url = reverse_lazy('home')
同时使用如下重置密码邮件模板:
Someone asked for password reset for email {{ email }}. Follow the link below: {{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} PS : Please do not reply to this email
但邮件模板上下文的protocol返回http而非https,请问问题出在哪里?
问题原因及解决方案
未配置Django安全相关设置:
Django默认根据请求的协议生成protocol值,如果生产环境使用HTTPS但Django未感知到真实请求协议,就会返回http。需要在settings.py中添加以下配置:# 强制跳转至HTTPS SECURE_SSL_REDIRECT = True # 让Django识别反向代理传递的HTTPS协议头 SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https') # 标记SESSION和CSRF Cookie仅通过HTTPS传输 SESSION_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True其中
SECURE_PROXY_SSL_HEADER专门用于应用部署在反向代理(如Nginx、Docker容器代理)之后的场景,确保Django能获取到真实的请求协议。自定义视图未强制指定protocol:
可以在重写的ResetPasswordView中直接重写get_protocol方法,固定返回https:class ResetPasswordView(SuccessMessageMixin, PasswordResetView): # 原有属性配置... def get_protocol(self): return 'https'这种方式适合无需根据环境动态切换协议的场景,比如固定使用HTTPS的生产环境。
Docker反向代理未传递协议头:
如果使用Docker部署应用,反向代理(如Nginx)需要正确传递请求的协议头信息。示例Nginx配置需添加:proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $remote_addr;确保Django能通过
X-Forwarded-Proto头获取到真实的HTTPS协议。
内容的提问来源于stack exchange,提问作者Mereva
相关产品推荐
相关产品推荐

