アプリでの認証に Passport を使用しており、Express も使用しています。私の問題を要約すると、ログイン機能は最初は正常に機能しますが、ユーザーのセッションがタイムアウトした後、ユーザーはログインできなくなります。
認証に標準のローカル戦略を使用しています。
私のセットアップに基づいて、できるだけ単純な例を含めます。
//-------------
//Set up authentication with Passport
//-------------
var userModel = require('./models/user')(db);
passport.use(new LocalStrategy(
function(username, password, done) {
var errorMessage = 'Incorrect username/password combination.';
userModel.GetUserByUsername(username, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: errorMessage });
}
user.validatePassword(password, function(isPasswordCorrect) {
if (!isPasswordCorrect)
{
return done(null, false, { message: errorMessage });
}
//Update with login date
userModel.UpdateUserWithLogin(username, user.currentLoginTime, function(err){
//if we have an error here, we should probably just log it
if(err)
{
console.log(err);
}
});
return done(null, user);
});
});
}
));
passport.serializeUser(function(user, done) {
done(null, user);
});
passport.deserializeUser(function(user, done) {
userModel.GetUserByUsername(user._id, function(err, user) {
done(err, user);
});
});
//-------------
//Set up express and configure
//-------------
var sessionStore = new SkinStore(db);
var app = express();
app.configure(function(){
app.set('port', process.env.PORT || 3000);
app.set('views', __dirname + '/views');
app.engine('html', consolidate.swig);
app.set('view engine', 'html');
swig.init({
root: '.',
allowErrors: true, // allows errors to be thrown and caught by express instead of suppressed
autoescape: false});
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser("[mysecrethere]"));
app.use(express.session({ store: sessionStore,
cookie: { expires : new Date(Date.now() + 3600000) } //1 Hour
}));
app.use(passport.initialize());
app.use(passport.session());
app.use(flash());
app.use(expressValidator);
app.use(express.static(path.join(__dirname, 'public')));
//Dynamic helpers
app.use(require('./helpers/DynamicHelpers'));
app.use(app.router);
});
app.get('/login', routes.login);
app.post('/login', passport.authenticate('local', {failureRedirect: '/login',
badRequestMessage: "Please enter username and password",
failureFlash: true }),
function(req, res) {
var targetUrl = req.session.pageAfterLogin;
delete req.session.pageAfterLogin;
res.redirect(targetUrl || '/account');
});
app.get('/account', IsAuthenticated, routes.account.show);
IsAuthenticated ヘルパー関数:
function IsAuthenticated(req,res,next){
if(req.isAuthenticated())
{
next();
}
else
{
//save the requested page and then redirected
req.session.pageAfterLogin = req.url;
req.flash("error", "You must be logged in first!");
res.redirect('/login');
}
}
デバッグでわかることは、認証が成功した後 (および Cookie の有効期限が切れた後)、次のロジックにヒットしたことです (上記から)。
function(req, res) {
var targetUrl = req.session.pageAfterLogin;
delete req.session.pageAfterLogin;
res.redirect(targetUrl || '/account');
}
「req」でセッションが適切に設定され、Passport 情報が適切に保存されていることがわかります。その後、リダイレクトが発生し、新しいリクエストにはセッション情報が保存されず、まったく新しいセッション ID が割り当てられます。クライアントに Cookie が設定されていないのではないかと疑っていましたが、そのように見えます。これは、一貫したセッションの欠如を説明するはずです。
ただし、新しい Cookie が設定されていない理由がわかりません。これが起こっている理由を示すアプリの構成方法に何か問題がありますか?
Node.js インスタンスを再起動すると問題が解決することを付け加えておきます。これは、本番環境で許容できるものではありません。
ありがとう。
更新: HTTP/S トラフィックで何が起こっているかを確認するために Fiddler を実行しました。最初に機能したときに、ブラウザーに設定された Cookie を取得していることがわかります (いくつか試しました)。その後のリクエスト。
それが機能しない場合、ブラウザーはサーバーに Cookie を渡していないため、Node は毎回新しい Cookie を提供する Set-Cookie ヘッダーを送信しています。これまでのところ、この原因を特定することはできませんでした。