Django allauth未使用https发送链接

14

我希望Django Allauth发送像确认电子邮件或重置密码的链接时使用https

类似这样的内容:

https://example.com/ca/accounts/confirm-email/picuwfpjpptjswi50x5zb4gtsqptmwkscea445kadnbsfwcyij3fdnblery4onuq/

根据官方文档,只需更改settings.py中的以下设置即可:

ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"

但我一直得到的链接是使用 http 而不是 https,就像这样:

http://example.com/ca/accounts/confirm-email/picuwfpjpptjswi50x5zb4gtsqptmwkscea445kadnbsfwcyij3fdnblery4onuq/

我是否漏掉了什么?谢谢!

3个回答

18

仔细研究代码,你会发现allauth使用Django内置的build_absolute_uri方法来设置activate_url模板上下文变量:

https://github.com/pennersr/django-allauth/blob/master/allauth/account/models.py#L119

...
activate_url = reverse("account_confirm_email", args=[self.key])
activate_url = request.build_absolute_uri(activate_url)
ctx = {
"activate_url": activate_url,
...
}

查看 build_absolute_uri 的代码,你可以看到它需要一个环境变量:

https://github.com/django/django/blob/master/django/http/request.py#L153

def _get_scheme(self):
    return 'https' if os.environ.get("HTTPS") == "on" else 'http'

要在此函数生成的URL中返回https://,您需要设置HTTPS环境变量。

这取决于您如何设置项目,但您可以在settings.pymanage.py设置环境变量

以下是关于Django SSL安全性的良好帖子:

编辑

奇怪的是,重置密码模板使用了一种不同的方法构建URL:

https://github.com/pennersr/django-allauth/blob/master/allauth/account/forms.py#L428

url = '%s://%s%s' % (app_settings.DEFAULT_HTTP_PROTOCOL,
    current_site.domain,
    path)
context = {"site": current_site,
    "user": user,
    "password_reset_url": url}

使用DEFAULT_HTTP_PROTOCOL设置代替


通过你的解决方案,现在密码重置电子邮件是使用https发送的,但确认电子邮件地址仍然是http。有任何想法为什么? - ferrangb
看一下更新。似乎重置密码模板使用了不同的URL构建方式。你确定变量被正确设置了吗? - Timmy O'Mahony
确认电子邮件地址的消息仍然无法正常工作。我首先尝试在settings.py中设置变量(import os os.environ['HTTPS'] = "on"),然后在终端中手动设置(HTTPS="on"; export HTTPS),但我仍然收到使用http的确认电子邮件地址消息。 - ferrangb
感谢您的帮助,我成功解决了问题!我还报告了这个bug,它将在下一个django-allauth版本中得到解决:https://github.com/pennersr/django-allauth/issues/717 谢谢! :) - ferrangb

2

如果您在代理后使用 Django,您需要将 HTTPS 标头发送到 Django。 在 Apache2 中对我有效的方法是将以下内容放置在 Apache2 上:

<VirtualHost *:443>
  RequestHeader set X-Forwarded-Proto 'https' env=HTTPS

在添加头文件 mod 之后:
a2enmod headers

这是关于Django的setting.py文件:

USE_X_FORWARDED_HOST = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

现在我的所有build_absolute_uri都以https开头,模板也是如此,包括密码恢复和认证邮件。


2
除了设置“HTTPS”环境变量和SECURE_PROXY_SSL_HEADER SECURE_SSL_REDIRECT之外,当在adapter.py的render_mail()中使用.txt body时,在渲染模板和使用EmailMultiAlternatives()发送邮件时也可能出现问题。[1]: https://github.com/pennersr/django-allauth/blob/master/allauth/account/adapter.py
for ext in ["html", "txt"]:
        try:
            template_name = "{0}_message.{1}".format(template_prefix, ext)
            bodies[ext] = render_to_string(
                template_name,
                context,
                self.request,
            ).strip()
        except TemplateDoesNotExist:
            if ext == "txt" and not bodies:
                # We need at least one body
                raise
    if "txt" in bodies:
        msg = EmailMultiAlternatives(subject, bodies["txt"], from_email, to)
        if "html" in bodies:
            msg.attach_alternative(bodies["html"], "text/html")
    else:
        msg = EmailMessage(subject, bodies["html"], from_email, to)
        msg.content_subtype = "html"  # Main content is now text/html
    return msg

例如,print(bodies[ext]) 的输出结果为:
  "To confirm this is correct, go to " https://127.0.0.1:8000/accounts/confirm-email/MjI:1kS0Mj:M5YfUf9-1Vg_TlgjVrK6vAtaLDE/ "

但是在电子邮件上仍然是http://。
 http://url7514.sitename/ls/click?upn=HJL2SSWV...

大多数设备也可以正常工作,因为应该仍然被重定向到https://,但是有些设备不行,所以必须在默认模板/帐户/电子邮件/电子邮件确认消息.txt中更改为HTML扩展名, 结果如下:

要确认这是正确的,请转到https://sitename/accounts/confirm-email/M...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接