我正在嘗試使用node-openid(通過passport-google)通過他們的Google憑據對我的用戶進行身份驗證。它在我的開發機器上工作正常,但是當我用2個dynos將它部署到Heroku時,它在一個dyno處理整個OpenID對話時起作用,並且當對話在一個dyno上開始並在第二個時完成時失敗。在這種情況下,我得到以下錯誤:如何在Heroku上用多個dyno使用node-openid?
2013-01-15T15:18:24+00:00 app[web.2]: Failed to verify assertion (message: Invalid association handle)
2013-01-15T15:18:24+00:00 app[web.2]: at Strategy.authenticate.identifier (/app/node_modules/passport-google/node_modules/passport-openid/lib/passport-openid/strategy.js:143:36)
...
什麼是處理這個問題的正確方法?我是否應該將對話狀態保存在數據庫中,以便兩個dynos都可以訪問它?
更新:
下面是我使用的存儲MongoDB中的ASSOCATION解決問題的代碼。
var
GoogleStrategy = require('passport-google').Strategy;
// We have to save the OpenID state in the database so it's available to both
// dynos.
db.collection('OpenID').ensureIndex({expires: 1}, {expireAfterSeconds: 0},
function(err, result) {
if (err) {
throw new Error('Error setting TTL index on OpenID collection.');
}
});
// Use the GoogleStrategy within Passport.
// Strategies in passport require a `validate` function, which accept
// credentials (in this case, an OpenID identifier and profile), and invoke a
// callback with a user object.
strategy = new GoogleStrategy({
returnURL: 'http://localhost:3000/auth/google/return',
realm: 'http://localhost:3000/'
},
function(identifier, profile, done) {
// asynchronous verification, for effect...
process.nextTick(function() {
// To keep the example simple, the user's Google profile is returned to
// represent the logged-in user. In a typical application, you would want
// to associate the Google account with a user record in your database,
// and return that user instead.
profile.identifier = identifier;
return done(null, profile);
});
}
);
strategy.saveAssociation(function(handle, provider, algorithm, secret, expiresIn, done) {
db.collection("OpenID").insert({
handle: handle,
provider: provider,
algorithm: algorithm,
secret: secret,
expires: new Date(Date.now() + 1000 * expiresIn)
}, done);
});
strategy.loadAssociation(function(handle, done) {
db.collection("OpenID").findOne({handle: handle}, function (error, result) {
if (error)
return done(error);
else
return done(null, result.provider, result.algorithm, result.secret);
});
});
你能提供一些關於你如何解決這個問題的細節嗎?我實際上使用一些中間件(passport-google)來執行此身份驗證。 Passport設置爲使用Redis商店進行會話。你能讓我知道你必須做什麼才能做到這一點? – electrichead
@electrichead,我在上面添加了我的代碼。 –
@DavidBraun您如何設置'saveAssocation' /'loadAssociation'?在這種情況下,「策略」是什麼? – kynan