5

次のように、機能するログインテストを設定しました。

var express = require('express');
var fs = require('fs');
var http = require('http');
var path = require('path');
var routes = require('./routes/index.coffee');
var passport = require('passport');

var LocalStrategy = require('passport-local').Strategy;
var User = require('./userdb.coffee');
var app = express();
var RedisStore = require('connect-redis')(express);

passport.use(new LocalStrategy(function(username, password, done) {
  return User.findOne({
    username: username
  }, function(err, user) {
    if (err) {
      return done(null, false, message: error);
    }
    if (!user) {
      return done(null, false, {
        message: 'Unknown user'
      });
    }
    if (!user.validPassword(password)) {
      return done(null, false, {
        message: 'Invalid password'
      });
    } else {
      return done(null, user);
    }
  });
}));

passport.serializeUser(function(user, done) {
  return done(null, user);
});

passport.deserializeUser(function(user, done) {
  return done(null, user);
});

app.configure(function() {
  app.set('port', process.env.PORT || 5003);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.enable('trust proxy');
  app.use(express["static"](path.join(__dirname, 'public')));
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieParser('SOMESECRET'));
  app.use(express.session({
    cookie: {
      maxAge: 10 * 60 * 1000
    },
    key: 'express.sid',
    secret: 'SOMESECRET',
    store: new RedisStore({
      port: 6379,
      host: 'localhost'
    })
  }));
  app.use(passport.initialize());
  app.use(passport.session());
  return app.use(app.router);
});

var check_auth = function(req, res, next) {
  if (req.isAuthenticated()) {
    console.log(req.session.cookie.expires);
    return next();
  }
  return res.redirect('/login');
};

app.get('/', check_auth, routes.index);
app.get('/login', routes.login);
app.get('/logout', routes.logout);
app.post('/authenticate', passport.authenticate('local', {
  successRedirect: '/',
  failureRedirect: '/login'
}));

app.listen(app.get('port'), '0.0.0.0');

ルートとユーザー ロジックは、私の問題とは無関係だと思うので省略しますが、必要に応じて喜んで共有します (非常に小さいため、概念の小さな証明を実行するためだけです)。 .

ログインが機能し、セッションが機能し、セッション値に基づいてテンプレートがレンダリングされます。 私の問題は maxAge/expires にあります。問題がどこにあるのかわかりませんが、説明してみます。

ログインすると、セッションが で保存passport.jsされ、正しく保存さRedisStoreれ、セッションを指す Cookie がブラウザに返されます。後続のリクエストでは、Cookie が正常に検出され、 my からの正しいセッションを指していますSessionStorereq.session.cookieUPDATEDexpiresを表示し、私のredisサーバーでは、TTL が 10 分 (600) にリセットされます。

私の問題は、Cookie がブラウザー (Chrome、Windows、および Mac) で同じ有効期限にとどまることです。

だから私の質問は:どうすればこれをさらにデバッグできますか? req.session が (によってexpresspassportおよびconnect-redis内部的に/自動的に) 更新されるので、問題がどこにあるのか、これを修正するにはどうすればよいのか疑問に思っています: Cookie は最初の maxAges/expires のままです。

ヒント、ポインタ、またはアイデアをいただければ幸いです。

4

3 に答える 3

5

Express-session は、ローリング Cookie の有効期限をサポートしています。残念ながら、それは最近文書化されたばかりです。

セッションには「ローリング」オプションを使用してください。これにより、「すべての応答に強制的に Cookie が設定され」、「有効期限がリセットされます」。ローリングを true に設定します。

「再保存」オプションにも注意してください。それは「変更されていない場合でもセッションを強制的に保存します...」そのオプションもtrueに設定することをお勧めします。このオプションのデフォルト値は true ですが、明示的に値を設定する必要があることに注意してください。このオプションを明示的に設定するのではなく、デフォルトに依存することは非推奨になりました。

次のようなものを試してください:

app.use( session( { secret: 'keyboard cat',
                    cookie: { maxAge: 60000 },
                    rolling: true,
                    resave: true, 
                    saveUninitialized: false
                  }
         )
);

これがドキュメントです。「オプション」と「options.resave」の下を見てください: https://github.com/expressjs/session

于 2014-12-22T19:39:14.087 に答える
1

掘り下げた結果、Express はこの種のローリングをサポートしていないことがわかり、プログラマーが実装する課題として残されています。

ブラウザの有効期限が確実に読み取れる場合に役立つため、有効期限がexpress近づいたときにのみセッションをバンプできますが、私はこれを回避策として (非効率的に) 使用します。

check_auth = function(req, res, next) {
  console.log(req.isAuthenticated());
  if (req.isAuthenticated()) {
    if (req.session.roll) {
      req.session.roll = 0;
    } else {
      req.session.roll = 1;
    }
    return next();
  }
  return res.redirect('/login');
};

どこrollにでもある可能性がありますが、セッションであるポイントが変更されます(認証チェックされたリクエストごとに*)。

*) これは非常に非効率的であることも意味しますが、今のところ問題ありません。

1 つの代替方法は、セッション ID の TTL を検索することです。これは次のような方法で確認する必要があります: ttl < 10% * maxAge (アプリで定義) の場合、TTL は実際にはすべての要求で正しく更新されるため、Set-Cookie が送信されないだけです。そのため、ユーザーが maxAge の 90% 以内にとどまると、ブラウザーの Cookie は最終的に期限切れになるため、そのアプローチでも十分ではありません。しかし、それは良い中間点かもしれません。

他の人がより良い解決策を検討することを奨励するために、私は質問を受け入れないままにします.

于 2012-10-26T23:58:30.017 に答える