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

Вход в паспорт и постоянный сеанс

Фон

У меня есть приложение MEAN с возможностями CRUD, полностью протестированными с почтальоном. Я уже давно пытаюсь найти логин без везения. Я прочитал и попробовал следующее

Но я только смог зарегистрировать и зарегистрировать пользователя, а не настаивать на входе в сеанс.

Мое приложение

Здесь - ссылка на полное github repo (если вы ищете последние изменения, проверьте развитие ветки)

Мое понимание Auth/Login

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

Настройка паспорта

У меня есть следующий файл auth.js, он configs паспорт

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function(app, user){

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

  // passport config
  passport.use(new LocalStrategy(user.authenticate()));

  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    user.findById(id, function(err, user) {
      console.log('no im not serial');
      done(err, user);
    });
  });
};

Это вызывается в файле сервера, например

//code before
var user    = require('./models/user.js');
var auth    = require('./modules/auth.js')(app, user);
// code after

Маршрутизация для входа

В моих маршрутах у меня есть логин, как показано ниже.

router.post('/login', function(req, res, next) {

  passport.authenticate('local', function(err, user, info) {

    if (err) {
        return next(err);
    }

    if (!user) {
        return res.status(401).json({
            err: info
        });
    }

    req.logIn(user, function(err) {

        if (err) {
            return res.status(500).json({
                err: 'Could not log in user'
            });
        }

        res.status(200).json({
            status: 'Login successful!'
        });

    });
  })(req, res, next);
});

Этот маршрут работает, как проверено с почтальоном. Я ввожу детали "joe" и "pass" и получаю следующий ответ.

введите описание изображения здесь

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

введите описание изображения здесь

Итак, что дальше?

Вот где я заблудился. У меня есть несколько вопросов.

  • Является ли пользователь сейчас в сеансе на моем сервере?
  • Должен ли я отправить req.session.passport.user обратно клиенту?
  • Нужен ли мне идентификатор сеанса для всех будущих запросов?

Тестирование сеанса

У меня есть вторая настройка маршрута для тестирования сеанса следующим образом

router.get('/checkauth', passport.authenticate('local'), function(req, res){

    res.status(200).json({
        status: 'Login successful!'
    });

});

Часть passport.authenticate('local') (я думал) есть, чтобы проверить, существует ли пользовательский сеанс до предоставления доступа к маршруту, но я никогда не получаю ответ 200, когда я его запускаю, даже после входа в систему.

Ожидает ли этот маршрут req.session.passport.user в голове или как аргумент данных в HTTP-запросе, для которого требуется auth?

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

4b9b3361

Ответ 1

Является ли пользователь сейчас в сеансе на моем сервере?

Нет. Для фактического хранения сеанса в памяти/базе данных вам необходимо использовать промежуточное ПО express-session до app.use(passport.session());. Это промежуточное программное обеспечение отвечает за настройку файлов cookie для браузеров и конвертирует файлы cookie, отправленные браузерами в объект req.session. PassportJS использует этот объект только для дальнейшей десериализации пользователя.

Должен ли я отправить req.session.passport.user обратно клиенту?

Если ваш клиент ожидает ресурс user при входе в систему, то вам следует. В противном случае я не вижу причин для отправки пользовательского объекта клиенту.

Нужен ли мне идентификатор сеанса для всех будущих запросов?

Да, для всех будущих запросов требуется идентификатор сеанса. Но если ваш клиент является браузером, вам не нужно ничего отправлять. Браузер будет хранить идентификатор сеанса как файл cookie и отправит его для всех последующих запросов до истечения срока действия файла cookie. express-session прочитает этот файл cookie и добавит соответствующий объект сеанса как req.session.

Тестирование сеанса

passport.authenticate('local') предназначен для аутентификации учетных данных пользователя из тела POST. Вы должны использовать это только для логина.

Но чтобы проверить, проверен ли пользователь на всех других маршрутах, вы можете проверить, существует ли req.user.

function isAuthenticated = function(req,res,next){
   if(req.user)
      return next();
   else
      return res.status(401).json({
        error: 'User not authenticated'
      })

}
router.get('/checkauth', isAuthenticated, function(req, res){

    res.status(200).json({
        status: 'Login successful!'
    });
});

Ответ 2

Как говорит @hassansin, вам нужно использовать промежуточное программное обеспечение, которое реализует управление сеансом. Паспорт .session() промежуточное программное обеспечение заключается в том, чтобы связать структуру паспорта с руководством сеанса и не выполнять сеанс сам по себе. Вы можете использовать express-session промежуточное программное обеспечение для реализации управления сеансом. Вы должны изменить свой auth.js следующим образом

var passport = require('passport');
var session = require('express-session');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function(app, user){
  app.use(session({secret: 'some secret value, changeme'}));    

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

  // passport config
  passport.use(new LocalStrategy(user.authenticate()));

  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    user.findById(id, function(err, user) {
      console.log('no im not serial');
      done(err, user);
    });
  });
};

Обратите внимание, что в этом случае механизм сеанса использует хранилище в памяти, и он не работает, если вы масштабируете приложение и применяете балансировку нагрузки. Когда вы достигнете этого состояния разработки, вам понадобится нечто вроде хранилища сеансов connect-redis.

Также обратите внимание, что вам нужно изменить секретное значение, используемое в вызове midleware сеанса, и использовать одно и то же значение во всех экземплярах приложения.

Ответ 3

В соответствии с паспортной документацией req.user будет установлен для аутентифицированного пользователя. Для того, чтобы это работало, вам понадобится модуль express-session. Вам не нужно ничего больше, кроме того, что у вас уже есть для работы паспорта.

Что касается тестирования сеанса, вы можете иметь функцию промежуточного программного обеспечения, которая проверяет, установлен ли req.user, если это так, мы знаем, что пользователь аутентифицирован, а если нет, вы можете перенаправить пользователя.

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

authenticated.js

module.exports = function (req, res, next) {
    // if user is authenticated in the session, carry on
    if (req.user) {
        next();
    }
    // if they aren't redirect them to the login page
    else {
        res.redirect('/login');
    }
};

контроллер

var authenticated = require('./authenticated');

router.get('/protectedpage', authenticated, function(req, res, next) {
    //Do something here
});

Ответ 4

Я не знаю, как проверить все существующие сеансы, но Passport обрабатывает выдачу идентификаторов сеансов. Попробуйте проверить, что у вас есть req.user на конечной точке тестирования после входа в