Django allauth没有发送与https的链接

时间:2014-09-13 15:19:29

标签: django https django-allauth

我希望Django Allauth使用https发送确认电子邮件或重设密码等链接:

这样的事情:

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

根据the official documentation仅更改settings.py中的以下设置,它应该有效:

ACCOUNT_DEFAULT_HTTP_PROTOCOL = "https"

但是我继续使用http而不是https获取链接:

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

我错过了什么吗?谢谢!

3 个答案:

答案 0 :(得分:5)

稍微深入研究一下代码,您可以看到allauth使用Django的activate_url方法构建build_absolute_uri模板上下文变量:

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'

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

这取决于您设置项目的方式,但您可以settings.pymanage.py

set the environment variable https://security.stackexchange.com/questions/8964/trying-to-make-a-django-based-site-use-https-only-not-sure-if-its-secure

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

修改

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

{{3}}

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设置

答案 1 :(得分:1)

除了设置“ HTTPS”环境变量和SECURE_PROXY_SSL_HEADER SECURE_SSL_REDIRECT,当在适配器中使用.txt正文时,渲染模板并使用EmailMultiAlternatives()发送邮件时也可能出现问题。pyrender_mail() [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(body [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://,但在某些设备上则不能,因此必须将默认模板/account/email/email_confirmation_message.txt更改为html扩展名, 结果之后:

To confirm this is correct, go to https://sitename/accounts/confirm-email/M...

答案 2 :(得分:0)

如果您在代理后面使用 django,则必须向 django 发送 https 标头。 在 apache2 中对我有用的是把它放在 apache2 上

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

添加标题后:

a2enmod headers

这在 django setting.py 上:

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

有了这个,我所有的 build_absolute_uri 都以 https 开头,模板也是如此,这包括密码恢复和身份验证邮件。