Что делает промежуточное ПО Passport.session ()?

125

Я создаю систему аутентификации, используя Passport.js, используя Easy Node Authentication: Setup и Local tutorial .

Я не понимаю, что passport.session()делает.

Поигравшись с различным промежуточным программным обеспечением, я понял, что express.session()это то, что отправляет идентификатор сеанса через файлы cookie клиенту, но я не понимаю, что passport.session()делает и почему это требуется в дополнение к express.session().

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

// Server.js настраивает приложение и настраивает веб-сервер

//importing our modules
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

var configDB = require('./config/database.js');

//Configuration of Databse and App

mongoose.connect(configDB.url); //connect to our database

require('./config/passport')(passport); //pass passport for configuration

app.configure(function() {

    //set up our express application

    app.use(express.logger('dev')); //log every request to the console
    app.use(express.cookieParser()); //read cookies (needed for auth)
    app.use(express.bodyParser()); //get info from html forms

    app.set('view engine', 'ejs'); //set up ejs for templating

    //configuration for passport
    app.use(express.session({ secret: 'olhosvermelhoseasenhaclassica', maxAge:null })); //session secret
    app.use(passport.initialize());
    app.use(passport.session()); //persistent login session
    app.use(flash()); //use connect-flash for flash messages stored in session

});

//Set up routes
require('./app/routes.js')(app, passport);

//launch
app.listen(port);
console.log("Server listening on port" + port);
Жорж Кринкер
источник

Ответы:

139

passport.session() действует как промежуточное программное обеспечение для изменения объекта req и изменения значения 'user', которое в настоящее время является идентификатором сеанса (из клиентского файла cookie), на истинный десериализованный объект пользователя.

Хотя в других ответах есть несколько хороших моментов, я подумал, что можно представить более конкретные детали.

app.use(passport.session());

эквивалентно

app.use(passport.authenticate('session'));

Где «сессия» относится к следующей стратегии, которая связана с паспортомJS.

https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

В частности, строки 59-60:

var property = req._passport.instance._userProperty || 'user';
req[property] = user;

Где он, по сути, действует как промежуточное ПО и изменяет значение свойства user в объекте req, чтобы содержать десериализованную личность пользователя. Чтобы разрешить это , чтобы работать правильно , вы должны включать в себя serializeUserи deserializeUserфункции в пользовательском коде.

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

passport.deserializeUser(function (user, done) {
    //If using Mongoose with MongoDB; if other you will need JS specific to that schema.
    User.findById(user.id, function (err, user) {
        done(err, user);
    });
});

Это найдет правильного пользователя из базы данных и передаст его в качестве закрывающей переменной в обратный вызов, done(err,user);чтобы приведенный выше код в passport.session()может заменить значение 'user' в объекте req и перейти к следующему промежуточному программному обеспечению в куче.

lindsaymacvean
источник
эй, как я могу хранить данные пользователя только в сеансе, я не хочу напрямую хранить их в базе данных
Новичок
1
"в заголовках запроса"? нет только в объекте запроса
caub
Я заметил, что если стратегия сеанса может восстановить аутентификацию и десериализовать пользователя. Но, несмотря на это, аутентификация по-прежнему переходит к следующей стратегии, которой в моем сценарии является facebook auth. Интересно, в чем смысл стратегии сеанса, если он все еще продолжает вызывать следующие стратегии, даже если сеанс может восстановить пользователя.
nishant 09
15

Из документации

В приложении на основе Connect или Express для инициализации Passport требуется промежуточное программное обеспечение Passport.initialize (). Если ваше приложение использует постоянные сеансы входа в систему, также необходимо использовать промежуточное ПО Passport.session ().

и

сессии

В типичном веб-приложении учетные данные, используемые для аутентификации пользователя, передаются только во время запроса на вход. Если аутентификация прошла успешно, сеанс будет установлен и поддерживаться с помощью файла cookie, установленного в браузере пользователя.

Каждый последующий запрос будет содержать не учетные данные, а уникальный файл cookie, который идентифицирует сеанс. Для поддержки сеансов входа в систему Passport будет сериализовать и десериализовать пользовательские экземпляры в сеанс и обратно.

и

Обратите внимание, что включение поддержки сеанса является совершенно необязательным, хотя рекомендуется для большинства приложений. Если этот параметр включен, обязательно используйте express.session () перед паспортом .session (), чтобы убедиться, что сеанс входа в систему восстановлен в правильном порядке.

Джош С.
источник
1
Спасибо за быстрый ответ, но это не ответ на мой вопрос. Также обратите внимание, что если у вас есть экспресс-приложение и вы используете express.session (), на любом клиенте, который подключается к вашему экспресс-серверу (независимо от того, аутентифицирован он или нет), ему будет предоставлен сеанс через cookie. Это не зависит от того, находится ли он на защищенной от входа странице вашего приложения или нет. Я все еще хотел бы узнать разницу между обоими промежуточными программами.
Жорж Кринкер,
1
@GeorgesKrinker - это методы serializeUser () и deserializeUser. Промежуточное ПО Express восстановит информацию о сеансе, но это не обязательно связано с тем, как паспорт управляет информацией о пользователе. Это необходимо сделать после проведения экспресс-регидратации.
Джош С.
Что ж, у меня создалось впечатление, что методы serializeUser () и deserializeUser выполняются с аутентификацией () внутри маршрутов.
Жорж Кринкер,
@GeorgesKrinker Я так не думаю. Когда я использовал паспорт, я звонил .authenticate только при входе в систему.
Джош С.
app.post('/login', passport.authenticate('local'), ...
Джош С.
11

Хотя вы будете использовать PassportJsдля проверки пользователя как часть URL-адреса для входа в систему, вам все равно понадобится какой-то механизм для хранения этой информации о пользователе в сеансе и извлечения ее с каждым последующим запросом (т.е. сериализовать / десериализовать пользователя).

Таким образом, вы аутентифицируете пользователя с каждым запросом, даже если для этой аутентификации не нужно искать базу данных или oauth, как в ответе на вход. Таким образом, паспорт будет рассматривать аутентификацию сеанса также как еще одну стратегию аутентификации.

И чтобы использовать эту стратегию - которая названа session, просто используйте простой ярлык - app.use(passport.session()). Также обратите внимание, что эта конкретная стратегия потребует от вас реализации функций сериализации и десериализации по очевидным причинам.

uniwalker
источник
11

Он просто аутентифицирует сеанс (который заполняется express.session()). Это эквивалентно:

passport.authenticate('session');

как можно увидеть в коде здесь:

https://github.com/jaredhanson/passport/blob/42ff63c/lib/authenticator.js#L233

Джаред Хэнсон
источник
6
Что вы имеете в виду? Он запускается при каждом запросе и не обязательно имеет учетные данные для аутентификации. Не могли бы вы рассказать мне немного подробнее о рабочем процессе, который происходит при каждом запросе?
Жорж Кринкер
6
Да, он запускается по каждому запросу. Идентификатор сеанса, генерируемый Express, представляет собой уникальный идентификатор, который примерно эквивалентен токену аутентификации, который браузер отправляет с каждым запросом. Данные, хранящиеся в этом сеансе, используются для восстановления состояния аутентификации пользователя.
Джаред Хэнсон
Привет, @JaredHanson. Не могли бы вы взглянуть на это . Я нигде не мог найти ответ?
Сарас Арья
@JaredHanson Я пытаюсь использовать password.js для аутентификации на широко используемом сервере авторизации с открытым исходным кодом, совместимом с OAuth2. Но я получаю сообщение об ошибке. Вы готовы помочь решить проблему? Вот ссылка: stackoverflow.com/questions/38176236/…
DollarCoffee 04
@JaredHanson: Я заметил, что объект req, дополненный данными паспорта. Пользователя сразу после входа в систему через google-oauth, теряется, когда на сайте выполняется следующий запрос новой страницы. Это ожидаемое поведение? Тогда я не понимаю, как вернуть информацию о недавно вошедшем пользователе?
user1102171