Meteor - 成功登录服务器端后返回客户端

Posted

技术标签:

【中文标题】Meteor - 成功登录服务器端后返回客户端【英文标题】:Meteor - return to client after successful login server-side 【发布时间】:2018-04-24 18:19:47 【问题描述】:

我编写了我的自定义登录方法,但我在最后一步被阻止:客户端的有效登录。

我相信我在服务器端正确登录但没有客户端:

我得到了完整和正确的(时间戳一致)LoginTokens (when & hashedToken) 在数据库中。 在 minimongo 中,我可以访问我是所有者 (this.userId) 的所有文档。 允许登录尝试Accounts.validateLoginAttempt(function (attempt),包含正确的用户并且没有返回错误。 在客户端,在呼叫返回时,Meteor.loggingIn()falseMeteor.user()null 在服务器 Accounts.onLogin(function(user) 上返回正常的 user._id

所以我认为这是关于返回给客户的问题(如 user._id) - 但我迷路了,认为我需要一位经验丰富的评论家。

ps : 我有 accounts-base@1.4.0 & accounts-password@1.5.0

登录方式(正常从客户端调用)

Meteor.methods(

    logTwo (userfinal, passfinal) 

        // Consistency var check
        check(userfinal, String);
        const passwordValidator = digest: String, algorithm: String;
        check(passfinal, passwordValidator);

        // check user
        const getUser = Accounts.findUserByEmail(userfinal);
        if (!getUser) throw invalidLogin();

        // check password
        const checkPassword = Accounts._checkPassword(getUser, passfinal);
        if (checkPassword.error) throw invalidLogin();

        // get user's id
        var userID = getUser._id

        // logic here

        console.log('code verified'); // rightly printed
        // below, I tried with or without methodArguments (this, 'login', user: userfinal,password: passfinal,
        // and (this, 'login', '',
        Accounts._attemptLogin(this, 'login', user: userfinal,password: passfinal, 
            type: '2FALogin',
            userId: userID,
        );
    ,
);

Accounts.validateLoginAttempt(function (attempt) 
    console.log(attempt); // rightly printed

    if (attempt.type === '2FALogin' && attempt.methodName === 'login') 
        console.log('allowed'); // rightly printed
        return true;
    

    if (attempt.error) 
        console.log('login error: ' + attempt.error);
    

);

Accounts.validateLoginAttempt(function (attempt) (console.log(attempt)))的返回

 type: '2FALogin',
  allowed: true,
  methodName: 'login',
  methodArguments: 
   [ 'bob@bob.com',
      digest: '70bd58ff28477...', // digest here ok
       algorithm: 'sha-256'  ],
  user: 
    _id: '6i6vLjc8Ssg6SGJNf',
     createdAt: 2017-11-01T15:08:52.332Z,
     services:  password: [Object], resume: [Object] ,
     emails: [ [Object], [Object] ],
     _loggedIn: true,
    ,
  connection: 
    id: 'xFLv3XZWztxsdxckM',
     close: [Function: close],
     onClose: [Function: onClose],
     clientAddress: '127.0.0.1',
     httpHeaders: 
       'x-forwarded-for': '127.0.0.1',
        'x-forwarded-proto': 'ws',
        host: 'localhost:3000',
        'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/62.0.3202.89 Safari/537.36',
        'accept-language': 'fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7,la;q=0.6'   

【问题讨论】:

你有没有试过在方法中调用Meteor.loginWithPassword,当一切都验证了?也可能值得在方法中尝试this.setUserId 我猜这只是时间问题。我想当你的方法回调被调用时,用户文档还没有发布到客户端,因此还不可用。 @MasterAM 那么如何解决呢? 您需要Meteor.user() 文档做什么?您以后可以使用它吗(例如,从控制台)? 以后也不可用了。我考虑 Meteor.user() 只是为了验证客户端中的日志是否正常。 【参考方案1】:

我知道如何管理它。

    Meteor.loginWithPassword 不是一个选项,因为它不能在 Meteor.call source 内工作 我在调用返回时成功尝试了Meteor.connection.setUserId(response),但localStorage 中没有存储任何内容:所以每次刷新时,我都会退出。

我需要Accounts.callLoginMethod,来自accounts-base:

成功调用this.setUserId(id)的登录方法和 Accounts._setLoginToken 在服务器上并返回一个对象 字段id(包含用户ID),token(包含简历 令牌),以及可选的tokenExpires

另外,在方法中,我需要返回函数Accounts._attemptLogin(否则客户端无法处理)。

所以,继续:

在客户端

Accounts.callLoginMethod(
    methodName: 'logTwo',
    methodArguments: [
      
        user: userfinal,
        password: passfinal
      ,
    ],
    userCallback: function(error) 
      if (!error) 
        // handle return here
       
    
);

在服务器上

Meteor.methods(

    logTwo (options) 

        // Consistency var check
        const passwordValidator = digest: String, algorithm: String;
        check(options, 
            user: String,
            password: passwordValidator
        );


        // check user
        const getUser = Accounts.findUserByEmail(options.user);
        if (!getUser) throw invalidLogin();

        // check password
        const checkPassword = Accounts._checkPassword(getUser, options.password);
        if (checkPassword.error) throw invalidLogin();

        // get user's id
        var userID = getUser._id

        // logic here

        return Accounts._attemptLogin(this, 'login', '', 
            type: '2FALogin',
            userId: userID,
        );
    ,
);

Accounts.validateLoginAttempt(function (options) 

    if (options.type === '2FALogin' && options.methodName === 'login') 
        return true;
    

    if (options.error) 
        console.log('login error: ' + options.error);
    

);

【讨论】:

这东西需要在 Meteor 指南的某个地方。你愿意写一个关于实现自定义登录方法的简短部分吗? github.com/meteor/docs @FredStark 你说得对,我会的。但也许 Accounts 函数不在文档中,而且通常记录得很差的原因是因为它们可以在不通知的情况下更改..

以上是关于Meteor - 成功登录服务器端后返回客户端的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Meteor 中的服务器调用客户端方法?

Meteor 同步方法调用

HTTP常见状态码

Meteor 集合获取返回空数组但已订阅

如何在 Meteor 中使用客户端重新连接事件

CSDN日报20170220——《从安卓调整到服务端后的思考》