![](/img/trans.png)
[英]How to determine which part of the page I'm on in order to reflect that on my navigation bar?
[英]How to determine which session I'm on for OAuth reauthentication in Meteor?
我已经编写了自己的自定义身份验证以与我们的公司OAuth解决方案一起使用。 这样会导致向我发送OAuth访问和刷新令牌。 然后,我可以将这些令牌存储在Meteor数据库的用户集合中,但是当我想执行重新身份验证时,我需要能够找到正确的会话,以便能够找到需要用来刷新它的OAuth令牌。 由于用户可以从多个设备登录,因此使事情变得复杂。
这是我用于存储令牌并在服务器端发送结果的代码:
var userId = null;
var user = Meteor.users.findOne({username: userName});
if (!user) {
userId = Meteor.users.insert({username: userName});
} else {
userId = user._id;
}
logger.info("User logged in: " + userId);
var initToken = Accounts._generateStampedLoginToken();
var token = Accounts._hashStampedToken(initToken);
token.accessToken = result.data.access_token;
token.refreshToken = result.data.refresh_token;
token.ttl = result.data.expires_in;
// Need way to bind oath.loginTokens with Meteor resume token
Meteor.users.update(userId,
{$push: {'services.oauth.loginTokens': token}}
);
var rslt = {
userId: userId
};
return(rslt);
这是数据库中的结果记录:
"services" : {
"oauth" : {
"loginTokens" : [
{
"when" : ISODate("2014-06-17T17:51:24.635Z"),
"hashedToken" : "ErcosEo9rD+IuT3EyFb3DFS8Bf0enwLzkCIf/nP1JFE=",
"accessToken" : "bhafr3WBDS67EmZ9hFE20af83BJRPFQQS8NGpMlSH6NHVCOiTeTuTJ",
"refreshToken" : "enOAFkBcxB88FlATUh2m0E5NLLG0y8AojyIH5gItnJXdU6",
"ttl" : 3600
}
]
},
"resume" : {
"loginTokens" : [
{
"when" : ISODate("2014-06-17T17:51:24.637Z"),
"hashedToken" : "uhRZpGdBHnAVKvgBEm7oSWsdflOGRI2YrR9Q21iqjzp+Xc="
}
]
}
},
"username" : "lous"
从上面的内容中可以看到,我需要取消标记值之一的查找,以找到正确的oauth信息以进行可能的刷新。 然后,在客户端上,我执行以下所示的操作,但是问题是validateResult
返回的令牌与存储在数据库中的令牌不同,因此我无法跟踪属于我的会话。
Template.login.events({
'submit #login-form': function(e,t) {
e.preventDefault();
var id = t.find('#login-id').value,
password = t.find('#login-password').value;
var req = {id: id, password: password};
Accounts.callLoginMethod({
methodArguments: [req],
validateResult: function (result) {
var token = result.token;
window.localStorage.setItem('token', token);
subscribeToRequests();
$.mobile.changePage('#landingPage', {transition: 'slidefade'});
},
userCallback: function(error) {
if (error) {
console.log("Error: " + error.message);
alert("Login Failure");
}
}
});
return false;
}
});
为什么令牌会不一样? 关于如何解决此问题的任何建议? 然后,一旦我将令牌存储在客户端,Meteor是否提供了一种开箱即用的方式来测试令牌的有效性? 这是我用来尝试执行此操作的findUser方法:
Meteor.methods({
findUser: function(token) {
var user = null;
var hashedToken = Accounts._hashLoginToken(token);
if (this.userId) {
//TODO need user object to include token to do TTL check and reauth if necessary
user = Meteor.users.findOne({_id:this.userId});
var result = refreshUser(user);
if (result.err) {
throw { name: 'System Error', message: 'The following error occurred: ' + result.err
};
}
} else {
throw { name: 'System Error', message: 'No userId available. Please try again.'
};
}
return user;
}
});
在您的findUser
方法中,您可以调用Accounts._getLoginToken(this.connection.id)
以获取该连接的当前登录令牌。 然后,您可以查找与此值关联的OAuth访问令牌。
关于您的原始问题,为什么客户端上的result.token
与数据库中的不同:我认为您正在将未哈希的令牌( result.token
)与数据库中存储的哈希令牌进行比较。 如果是这种情况,您可以将result.token
传递到服务器,并通过Accounts._hashLoginToken
传递给它,然后再在数据库中查找它。
那有意义吗?
这就是我最终将OAuth令牌与Meteor会话令牌对齐的方式。
我在服务器端创建了以下Meteor.methods
,客户端仅在Accounts.callLoginMethod
的validateResult
中调用updateToken
,因此可以通过@emily在其答案中描述的方法找到我的oauth令牌。
它调用reauthenticateUser
每当应用程序启动或刷新最后,它调用logoutUser
当用户登录我们或会话超时。
updateToken: function() {
// Update oauth hash token with correct hashed token
var user = Meteor.users.findOne({'_id': this.userId});
var hashedToken = Accounts._getLoginToken(this.connection.id);
// Get last element for OAuth array (safely presuming the last one is the last oauth from current call stack) and update hashedToken
var oauthObj = _.last(user.services.oauth.loginTokens);
Meteor.users.update({'services.oauth.loginTokens': {$elemMatch: {hashedToken: oauthObj.hashedToken}}}, {$set: {'services.oauth.loginTokens.$.hashedToken': hashedToken}});
},
reauthenticateUser: function() {
var user = null;
if (this.userId) {
var hashedToken = Accounts._getLoginToken(this.connection.id);
user = Meteor.users.findOne({$and: [{'_id': this.userId}, {'services.oauth.loginTokens': {$elemMatch: {hashedToken: hashedToken}}}]});
// Get specific oauthTokens (keep in mind multiples per client)
var oauthTokens = _.findWhere(user.services.oauth.loginTokens, {'hashedToken': hashedToken});
var result = refreshUser(this.userId, user.username, oauthTokens);
if (result.err) {
throw { name: 'System Error', message: 'The following error occurred: ' + result.err
};
}
} else {
throw { name: 'System Error', message: 'No userId available. Please try again.'
};
}
return user;
},
logoutUser: function() {
var hashedToken = Accounts._getLoginToken(this.connection.id);
// Remove orphaned Oauth tokens
Meteor.users.update(
{$and: [{'_id': this.userId}, {'services.oauth.loginTokens': {$elemMatch: {hashedToken: hashedToken}}}]},
{$pull: {'services.oauth.loginTokens': {'hashedToken':hashedToken}
}});
return true;
}
一旦设置好,对我来说,很容易在刷新oauth令牌后更新它们,或者在用户注销后将其删除。
我不是meteorJS开发人员,但我将尝试建议解决问题的方法。
使用npm安装流星cookie来安装流星cookie。
接着:
var initToken = Cookie.get('initToken');
if(!initToken) {
initToken = Accounts._generateStampedLoginToken();
Cookie.set('initToken', initToken, {days: 30});
}
var token = Accounts._hashStampedToken(initToken);
token.accessToken = result.data.access_token;
token.refreshToken = result.data.refresh_token;
token.ttl = result.data.expires_in;
要么:
var token = Cookie.get('token');
if(!token) {
var initToken = Accounts._generateStampedLoginToken();
token = Accounts._hashStampedToken(initToken);
Cookie.set('token', token, {days: 30});
}
token.accessToken = result.data.access_token;
token.refreshToken = result.data.refresh_token;
token.ttl = result.data.expires_in;
也许我添加的内容有误,但我认为您已经理解了窍门。 (:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.