Подтвердить что ты не робот

Node.js + express.js + passport.js: оставаться аутентифицированным между перезагрузкой сервера

Я использую pass.js для обработки auth в приложении nodejs + express.js. Я настраиваю LocalStrategy для приема пользователей из mongodb

Мои проблемы в том, что пользователи должны повторно аутентифицироваться при перезагрузке сервера node. Это проблема, так как я активно ее разрабатываю и не хочу заходить в систему при каждом перезапуске... (+ я использую node supervisor)

Вот моя установка приложения:

app.configure(function(){
    app.use('/static', express.static(__dirname + '/static'));
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.session({secret:'something'}));
    app.use(passport.initialize());
    app.use(passport.session());
    app.use(app.router);
});

И настройка сериализации сеанса:

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

passport.deserializeUser(function(email, done) {
    User.findOne({email:email}, function(err, user) {
        done(err, user);
    });
});

Я попробовал решение, данное в блоге (удалил ссылку, поскольку она больше не существует) с помощью connect-mongodb без успеха

app.use(express.session({
    secret:'something else',
    cookie: {maxAge: 60000 * 60 * 24 * 30}, // 30 days
        store: MongoDBStore({
        db: mongoose.connection.db
    })
}));

EDIT дополнительная проблема: требуется только одно соединение (использование одного бесплатного сервиса mongohq, ограниченного связью)

EDIT 2 решение (как издание, так как я, моя репутация, не отвечает, чтобы ответить на мой вопрос к настоящему времени

Вот решение, которое я наконец нашел, используя соединение, инициированное мангустом

app.use(express.session({
    secret:'awesome unicorns',
    maxAge: new Date(Date.now() + 3600000),
    store: new MongoStore(
        {db:mongoose.connection.db},
        function(err){
            console.log(err || 'connect-mongodb setup ok');
        })
}));
4b9b3361

Ответ 1

Там есть openource, называемый connect-mongo, который делает именно то, что вам нужно - сохраняет данные сеанса в mongodb

Пример использования

(при повторном использовании открытого соединения mongoose):

var session = require('express-session');
var MongoStore = require('connect-mongo')(session);
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/sess');
app.use(express.session({
    secret:'secret',
    maxAge: new Date(Date.now() + 3600000),
    store: new MongoStore(
    // Following lines of code doesn't work
    // with the connect-mongo version 1.2.1(2016-06-20).
    //    {db:mongoose.connection.db},
    //    function(err){
    //        console.log(err || 'connect-mongodb setup ok');
    //   }
    {mongooseConnection:mongoose.connection}
    )        
}));

вы можете прочитать об этом здесь: https://github.com/kcbanner/connect-mongo

Ответ 2

Я использую connect-mongo так:

var MongoStore = require('connect-mongo');

var sess_conf = {
  db: {
    db: mydb,
    host: localhost,
    collection: 'usersessions' // optional, default: sessions
  },
  secret: 'ioudrhgowiehgio'
};

 app.use(express.session({
    secret: sess_conf.secret,
    maxAge: new Date(Date.now() + 3600000),
    store: new MongoStore(sess_conf.db)
  }));


[...]

// Initialize Passport!  Also use passport.session() middleware, to support
  // persistent login sessions (recommended).
  app.use(passport.initialize());
  app.use(passport.session());

Ответ 3

Это потому, что вы используете MemoryStore (по умолчанию) для сеансов. Посмотрите на этот код из памяти .js(часть рамок Connect):

var MemoryStore = module.exports = function MemoryStore() {
  this.sessions = {};
};

и этот фрагмент из session.js(Express)

function session(options){
    /* some code */
    , store = options.store || new MemoryStore
    /* some code */
}

Теперь вы должны понимать, что каждый перезапуск сервера сбрасывает MemoryStore. Чтобы сохранить данные, вам нужно использовать другой магазин сеансов. Вы можете даже написать свой собственный (не должно быть слишком сложно), хотя Redis (см. эта библиотека) может быть хорошим выбором (и это хорошо поддерживается Express).

//EDIT

Согласно документации Connect, вам достаточно, если вы реализуете методы get, set и destroy. Следующий код должен работать:

customStore = {
    get : function(sid, callback) {
        // custom code, for example calling MongoDb
    },
    set : function(sid, session, callback) {
        // custom code
    },
    destroy : function(sid, callback) {
        // custom code
    }
}    

app.use(express.session({
    store: customStore
}));

Вам просто нужно реализовать вызов MongoDb (или любой другой Db, хотя я по-прежнему рекомендую использовать nonpermament, например Redis) для хранения данных сеанса. Также прочитайте исходный код других реализаций, чтобы захватить идею.

Ответ 4

Это, вероятно, очевидно для опытных пользователей node, но он меня поймал:

Вам нужно настроить сеанс node - например,

app.use(session({secret: "this_is_secret", store: ...}));

перед инициализация сессии паспорта - например

app.use(passport.initialize());
app.use(passport.session());

Если вы сначала назовете паспорт .session(), он не будет работать (и он вас не предупредит). Я думал, что проблема связана с функциями сериализации/десериализации пользователя и впустую.

Ответ 5

Я использую mongoose, я попробовал код, представленный в ответах выше, и это не сработало для меня. Я получил эту ошибку, когда сделал:

Error: db object already connecting, open cannot be called multiple times

Однако это работает для меня:

app.use(express.session({
    secret:'secret',
    maxAge: new Date(Date.now() + 3600000),
    store: new MongoStore({mongoose_connection:mongoose.connection})
}))

Примечание. Если у вас нет MongoStore по какой-либо причине, вам нужно сделать:

npm install connect-mongo --save

то

var MongoStore = require('connect-mongo')(express)

Ответ 6

Что я закончил:

var expressSession = require('express-session');
var redisClient = require('redis').createClient();
var RedisStore = require('connect-redis')(expressSession);
...
app.use(expressSession({
    resave: true,
    saveUninitialized: true,
    key: config.session.key,
    secret: config.session.secret,
    store: new RedisStore({
        client: redisClient,
        host: config.db.host,
        port: config.db.port,
        prefix: 'my-app_',
        disableTTL: true
    })
}));

Работает для меня.

Ответ 7

Вам необходимо изменить хранилище, которое вы используете для своих сеансов. По умолчанию "MemoryStore" не продолжает хранить сеанс при остановке приложения. Проверьте экспресс-сессию на github, чтобы узнать больше о том, что есть в других магазинах, таких как mongo one. (Не помню имя)