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

337

Как бы вы объяснили непрофессионалу рабочий процесс методов сериализации и десериализации Passport?

  1. Куда user.idидти после того, passport.serializeUserкак был вызван?

  2. Мы звоним passport.deserializeUserсразу после него, где он вписывается в рабочий процесс?

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id); 
       // where is this user.id going? Are we supposed to access this anywhere?
    });
    
    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

Я все еще пытаюсь обернуть голову вокруг этого. У меня полнофункциональное приложение, и я не сталкиваюсь ни с какими ошибками.

Я просто хотел понять, что именно здесь происходит?

Любая помощь приветствуется.

Анубхав
источник

Ответы:

452
  1. Куда user.idидти после того, passport.serializeUserкак был вызван?

Идентификатор пользователя (вы указываете в качестве второго аргумента doneфункции) сохраняется в сеансе и позже используется для извлечения всего объекта через deserializeUserфункцию.

serializeUserопределяет, какие данные пользовательского объекта должны храниться в сеансе. Результат метода serializeUser прикрепляется к сеансу как req.session.passport.user = {}. Вот, например, это было бы (поскольку мы предоставляем идентификатор пользователя в качестве ключа)req.session.passport.user = {id: 'xyz'}

  1. Мы звоним passport.deserializeUserсразу после него, где он вписывается в рабочий процесс?

Первый аргумент deserializeUserсоответствует ключу пользовательского объекта, который был передан doneфункции (см. 1.). Таким образом, весь ваш объект извлекается с помощью этого ключа. Этот ключ здесь является идентификатором пользователя (ключом может быть любой ключ объекта пользователя, например, имя, адрес электронной почты и т. Д.). В deserializeUserэтом ключе сопоставляется с массивом / базой данных в памяти или любым ресурсом данных.

Выбранный объект присоединяется к объекту запроса как req.user

Визуальный поток

passport.serializeUser(function(user, done) {
    done(null, user.id);
});              
                  
                 
                 └─────────────────┬──→ saved to session
                                       req.session.passport.user = {id: '..'}
                                   
                                              
passport.deserializeUser(function(id, done) {
                   ┌───────────────┘
                   
                    
    User.findById(id, function(err, user) {
        done(err, user);
    });            └──────────────→ user object attaches to the request as req.user   
});
AB
источник
2
Так user.idсохраняется req.session.passport.userили userхранится какreq.session.passport.user
Anubhav
@AB Я написал код для поиска пользователя по идентификатору, который был передан методу десериализации в качестве первого параметра. Но в каждом запросе он извлекает пользователя из базы данных. Это делает потерю производительности для дБ. Что еще я должен написать для десериализации функции, чтобы проверить, существует ли она в сеансе или нет?
uzay95
2
@AB Я не понимаю, что ты предложил uzay95. Так что в моем сеансе у меня есть только user._id. Но при каждом запросе я должен использовать этот идентификатор для десериализации из базы данных, называемой findUserByID, и он будет помещен в req.user. Как мне избежать такого звонка при каждом запросе?
Занко
10
@Zanko Вы можете поместить весь пользовательский объект в данные сеанса, но это, как правило, не очень хорошая идея, поскольку у него могут быть другие побочные эффекты. Например, когда пользователь обновляет свое имя пользователя, вы также должны обновить данные сеанса, в противном случае вы получите билеты из-за «сломанной функции переименования». Это относительно безвредный пример. То же самое может случиться с битами разрешения или равнозначными конфиденциальными данными (упс ...). По сути, те же проблемы, с которыми вы всегда сталкиваетесь, если у вас есть дублирующиеся данные. TL; DR - не делай этого.
Макс Трукса
1
Если я не ошибаюсь, req.session.passport.user = {id: '..'}часть диаграммы немного смещена, и req.session.passport.user = 785352вместо нее должна быть там , где 785352есть user.id. У меня проблемы с консольной регистрацией, чтобы доказать это, но кажется, что это имеет смысл. Когда вы звоните done(null, user.id);, имеет смысл взять второй аргумент - user.idв данном случае - и назначить его req.session.passport.userвместо того, чтобы назначать его req.session.passport.user.id. Потому что, если вы вместо этого перейдете user? req.sesssion.passport.user.id = userне имеет смысла.
Адам Зернер
21

Для тех, кто использует коа и паспорт коа :

Знайте, что ключ для пользователя, установленный в методе serializeUser (часто это уникальный идентификатор для этого пользователя), будет храниться в:

this.session.passport.user

Когда вы устанавливаете в done(null, user)deserializeUser, где 'user' - это какой-то пользовательский объект из вашей базы данных:

this.req.user ИЛИ this.passport.user

по какой-то причине this.userконтекст Koa никогда не устанавливается при вызове done (null, user) в вашем методе deserializeUser.

Таким образом, вы можете написать свое промежуточное программное обеспечение после вызова app.use (passport.session ()), чтобы поместить его в this.user следующим образом:

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

Если вы не знаете, как работает serializeUser и deserializeUser, просто напишите мне в твиттере. @yvanscher

yvanscher
источник
Извините за некропостинг здесь, но у меня есть беспокойство после прочтения объяснения десериализации. Я разместил вопрос об этом здесь на SO: stackoverflow.com/questions/54154047/…
Питер Келлнер
Супер полезно, но все еще возникают некоторые проблемы при чтении пользователя с других маршрутов. Может кто-нибудь помочь мне здесь? stackoverflow.com/questions/60709882/…
Гарри Линкольн