在Meteor中正确使用onResetPasswordLink、OnRollmentLink和onEmailVerificationLink方法

在Meteor中正确使用onResetPasswordLink、OnRollmentLink和onEmailVerificationLink方法,meteor,iron-router,meteor-accounts,Meteor,Iron Router,Meteor Accounts,我想知道是否有人会提供一个MeteoPad或代码示例,说明如何在Meteor(iron:router)中正确使用上面列出的方法之一。我正在努力理解这些方法到底是如何与我的应用程序交互的,而且这些方法似乎足够新,因此没有多少关于如何正确使用它们的好文档。谢谢 根据文档: 您可以使用以下功能构建自己的用户界面,或者使用accounts ui包包含基于密码登录的交钥匙用户界面 因此,这些回调用于滚动您自己的自定义解决方案。但是,我建议使用以下软件包之一,其中帐户条目是我的首选解决方案: 结合使用和

我想知道是否有人会提供一个MeteoPad或代码示例,说明如何在Meteor(iron:router)中正确使用上面列出的方法之一。我正在努力理解这些方法到底是如何与我的应用程序交互的,而且这些方法似乎足够新,因此没有多少关于如何正确使用它们的好文档。谢谢

根据文档:

您可以使用以下功能构建自己的用户界面,或者使用accounts ui包包含基于密码登录的交钥匙用户界面

因此,这些回调用于滚动您自己的自定义解决方案。但是,我建议使用以下软件包之一,其中帐户条目是我的首选解决方案:

  • 结合使用

  • 或者使用,特别是如果您希望使用OAuth集成,如Facebook、Twitter等,以便使用此软件包处理电子邮件验证,请参阅


    • 我写了这个方法,希望我能给出一个很好的例子来说明如何使用它

      它应该与
      帐户.sendResetPasswordEmail
      帐户.resetPassword
      (和)结合使用

      基本上,假设您想要实现您自己的帐户UI系统,而不是使用
      帐户UI
      包或类似软件。如果您想拥有密码重置系统,您需要三件事:

    • 使用密码重置链接发送电子邮件的方法
    • 了解用户何时单击重置链接的方法
    • 实际重置密码的方法
    • 以下是流程应该如何工作:

    • 用户单击页面上显示“重置密码”的链接
    • 您可以找到该用户(可能是让他们输入他们的电子邮件地址),然后致电
      Accounts.sendResetPasswordEmail
    • 用户单击刚收到的电子邮件中的重置密码链接
    • 您的应用已加载并向帐户注册回调。onResetPasswordLink
    • 调用回调是因为URL中有一个带有密码重置令牌的特殊片段
    • 此回调可以显示一个特殊的UI元素,要求用户输入新密码
    • 应用程序使用令牌和新密码调用
      Accounts.resetPassword
    • 现在,用户已登录,他们有了新密码
    • 这有点复杂,因为它是最先进的定制流程。如果您不想处理所有这些回调和方法,我建议您使用一个现有的accounts UI包,例如
      accounts UI


      对于一些示例代码,请看一下
      帐户ui
      包的代码:

      好的,因此我将在这里发布我最后学习和做的内容,以便其他人可以将其用作参考。我也会尽力解释发生了什么

      从其他评论中可以看出,“done”函数传递给了Accounts。在****上,链接回调是让我大吃一惊的主要部分。此函数只做一件事-重新启用autoLogin。值得注意的是,“完成”功能/自动登录是核心“帐户”包的一部分,不能修改“自动登录”用于一种特殊情况:用户A尝试在用户B当前登录的计算机上重置其pw。如果用户A在提交新密码之前退出重置密码流,则用户B将保持登录状态。如果用户A完成重置密码流,则用户B注销,用户A登录

      用于处理accounts ui包中的“done”的模式,以及我最后所做的操作,将“done”分配给一个变量,然后该变量可以传递给模板事件处理程序函数,并在重置密码逻辑完成后运行。此变量分配需要在Accounts.on****链接回调中完成,但回调可以放在任何顶级客户端代码中(只需确保正确分配变量的范围)。我只是把它放在我的reset_password_template.js文件的开头(到目前为止我只做了重置密码的操作,但模式应该类似):

      客户端/重置密码\u template.js:

      // set done as a variable to pass
      var doneCallback;
      
      Accounts.onResetPasswordLink(function(token, done) {
        Session.set('resetPasswordToken', token);  // pull token and place in a session variable, so it can be accessed later 
        doneCallback = done;  // Assigning to variable
      });
      
      在****链接回调中使用这些功能的另一个挑战是了解应用程序如何“知道”已触发回调,以及应用程序需要做什么。由于iron:router与Meteor紧密集成,很容易忘记它是一个单独的包。记住这些回调是独立于iron:router编写的,这一点很重要。这意味着,当单击发送到您电子邮件的链接时,您的应用程序将在根级别(“/”)加载

      ***旁注-这里还有一些关于StackOverflow的其他答案,它们提供了与iron集成的方法:路由器,并为每个链路加载特定的路由。对我来说,这些模式的问题是它们看起来有点粗糙,与“流星”的方式不一致。更重要的是,如果核心流星团队决定改变这些注册链接的路径,这些路径将中断。我试着给路由器打电话。go('path');在on****链接回调中,但由于某些原因,这在Chrome和Safari中不起作用。我很想找到一种方法来处理这些电子邮件链接的特定路由,这样就不需要不断设置和清除会话变量,但我想不出一个好的解决方案

      总之,正如@stubailo在他的回答中所描述的,你的应用程序被加载(在根级别),回调被触发。一旦启动回调,就可以设置会话变量。您可以使用此会话变量,使用以下模式在根级别加载适当的模板:

      client/home.html(或您的landi
      {{#unless resetPasswordToken}}
        {{> home_template}}
      {{else}}
        {{> reset_password_template}}
      {{/unless}}
      
      // checks if the 'resetPasswordToken' session variable is set and returns helper to home template
      Template.home.helpers({
        resetPasswordToken: function() {
          return Session.get('resetPasswordToken');
        }
      });
      
      // if you have links in your template that navigate to other parts of your app, you need to reset your session variable before navigating away, you also need to call the doneCallback to re-enable autoLogin
      Template.reset_password_template.rendered = function() {
        var sessionReset = function() {
          Session.set('resetPasswordToken', '');
          if (doneCallback) {
            doneCallback();
          }    
        }
      
        $("#link-1").click(function() {
          sessionReset();
        });
      
        $('#link2').click(function() {
          sessionReset();
        });
      }
      
      Template.reset_password_template.events({
        'submit #reset-password-form': function(e) {
          e.preventDefault();
      
          var new_password = $(e.target).find('#new-password').val(), confirm_password = $(e.target).find('#confirm-password').val();
      
          // Validate passwords
          if (isNotEmpty(new_password) && areValidPasswords(new_password, confirm_password)) {
            Accounts.resetPassword(Session.get('resetPasswordToken'), new_password, function(error) {
              if (error) {
                if (error.message === 'Token expired [403]') {
                  Session.set('alert', 'Sorry, this link has expired.');
                } else {
                  Session.set('alert', 'Sorry, there was a problem resetting your password.');          
                }
              } else {
                Session.set('alert', 'Your password has been changed.');  // This doesn't show. Display on next page
                Session.set('resetPasswordToken', '');
                // Call done before navigating away from here
                if (doneCallback) {
                  doneCallback();
                }
                Router.go('web-app');
              }
            });
          }
      
          return false;
        }
      });
      
      Router.route('/', {
        name: 'homepage',
        action: function() {
          if (Session.get('resetPasswordToken')) {
            this.redirect('resetPassword', {token: Session.get('resetPasswordToken')});
          } else {
            this.render('home');
          }
        }
      });
      
      Router.route('/password/reset/:token', {
        name: 'resetPassword',
        action: function () {
          this.render('resetPassword');
        },
        data: function() {
          return {token: this.params.token};
        },
        onAfterAction: function () {
          Session.set('resetPasswordToken', '');
        }
      });
      
      Accounts.onResetPasswordLink(function(token, done){
        Session.set('resetPasswordToken', token);
        doneResetPassword = done;
      });