Meteor - 密码恢复/电子邮件确认动态 url

Meteor - Password recovery / Email confirmation dynamic url

基本上,我在 meteor 和 meteor startup 上使用 accounts-base 包,我设置了服务器模板应该用于找回密码邮件、邮件确认邮件等

例如,在我的 server/startup.js 流星启动时,我做了很多事情,例如:

  Accounts.urls.verifyEmail = function (token) {
        return Meteor.absoluteUrl(`verify-email/${token}`);
      };

  Accounts.emailTemplates.verifyEmail.html = function (user, url) {
        return EmailService.render.email_verification(user, url);
      };

问题是我的应用托管在多个主机名上,例如company1.domain.comcompany2.domain.com, company3.domain.com 并且如果客户想从 company1.domain.com 重置他的密码,提供的恢复 url 应该是 company1.domain.com/recovery.

如果另一个客户端尝试在 company2.domain.com 上连接,则恢复 url 应该是 company2.domain.com.

据我了解,这实际上是无法实现的,因为帐户包使用的方法是 "Meteor.absoluteUrl()",returns 服务器 ROOT_URL 变量(服务器一个)。

在客户端,我根据 window.location.href 做了很多事情,但在尝试重设密码或尝试确认电子邮件地址时,我似乎无法发送此 url 到服务器。

我正在尝试找到一种方法来根据客户端发出请求的主机 动态生成 url,但是由于 url 是在服务器端生成的,我找不到这样做的优雅方法。我想我可以在尝试重置密码或创建帐户并在那里动态设置 ROOT_URL 变量之前调用流星服务器方法,但这似乎不安全且有风险,因为两个人可以轻松尝试重置同样的时间框架,可能会把事情搞砸,否则人们可能会滥用它。

有没有办法从客户端告诉服务器我要为当前电子邮件生成的 URL 必须是客户端当前的位置? 我希望能够覆盖基于帐户的流星包中的某些功能并实现类似的功能:

 Accounts.urls.verifyEmail = function (token, clientHost) {
        return `${clientHost}/verify-email/${token}`;
      };

  Accounts.emailTemplates.verifyEmail.html = function (user, url) {
        return EmailService.render.email_verification(user, url);
      };

但我不确定这是否可行,在覆盖基础包的 "behind the scene" 功能方面我没有任何实际经验,我喜欢发生的一切,除了 url生成的总是一样的。

好的,所以我设法找到了一种方法来实现我正在寻找的东西,有点 hack-ish,但是嘿..

基本上,useraccounts 具有一项功能,即在寄存器 at-form 中的任何隐藏输入都将添加到用户配置文件中。所以我添加了一个隐藏字段来存储用户当前位置。

AccountsTemplates.addField({
  _id: 'signup_location',
  type: 'hidden',
});

渲染模板时,我用 jQuery 填充这个隐藏的输入。

Template.Register.onRendered(() => {
  this.$('#at-field-signup_location').val(window.location.href);
});

然后,当我实际发送 emailVerification 电子邮件时,我可以查找此值(如果可用)。

  Accounts.urls.verifyEmail = function (token) {
    return Meteor.absoluteUrl(`verify-email/${token}`);
  };

  Accounts.emailTemplates.verifyEmail.html = function (user, url) {
    const signupLocation = user.profile.signup_location;
    if (signupLocation) {
      let newUrl = url.substring(url.indexOf('verify-email'));
      newUrl = `${signupLocation}/${newUrl}`;
      return EmailService.render.email_verification(user, newUrl);
    }

    return EmailService.render.email_verification(user, url);
  };

所以这修复了注册流程,我可以对 resetPassword 和 resendVerificationUrl 使用类似的概念,因为 signupLocation 现在在用户配置文件中。

您可能应该在您的设置中保留每个子域的数组,并在用户配置文件中保留相应子域的 ID,这样如果您的域将来发生变化,那么引用仍然有效且一致。