0

Стратегия локальной аутентификации Passport не вызывается

13

Я, конечно, упустил что-то очевидное, но не могу разобраться. Функция, которую я передал конструктору LocalStrategy, не вызывается, когда форма входа отправляется.

Код:

var express = require('express');
var http = require('http');
var path = require('path');
var swig = require('swig');
var passport = require('passport');

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

passport.serializeUser(function(user, done) {
  console.log('Вызван serializeUser.');
  done(null, user.name);
});

passport.deserializeUser(function(id, done) {
  console.log('Вызван deserializeUser.');
  return done(null, {name: 'Oliver'});
});

passport.use(new LocalStrategy(
  function(username, password, done) {
    console.log('local strategy вызван с: %s', username);
    return done(null, {name: username});
  }));

var app = express();

app.set('port', process.env.PORT || 3000);
app.set('view engine', 'swig');
app.set('views', __dirname + '/views');
app.use(express.favicon());
app.use(express.logger('dev'));
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser('asljASDR2084^^!'));
app.use(express.session());
app.use(passport.initialize());
app.use(passport.session());
app.use(app.router);
app.use(require('less-middleware')({ src: __dirname + '/public' }));
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.errorHandler({ dumpExceptions:true, showStack:true }));

app.engine('swig', swig.renderFile);

app.post('/auth', passport.authenticate('local'));
app.get('/login', function(req, res) {
  // login - это простая форма, которая отправляет логин и пароль на /auth
  res.render('login', {});
});

http.createServer(app).listen(app.get('port'), function(){
  console.log('Express сервер слушает на порту ' + app.get('port'));
});

Форма на моей странице /login скопирована из документации Passport, кроме того, что я изменил адрес отправки на /auth вместо /login:

<form action="/auth" method="post">
    <div>
        <label>Имя пользователя:</label>
        <input type="text" name="username"/>
    </div>
    <div>
        <label>Пароль:</label>
        <input type="password" name="password"/>
    </div>
    <div>
        <input type="submit" value="Войти"/>
    </div>
</form>

Когда я отправляю форму входа, логируется следующее:

GET /login 200 5ms - 432b
POST /auth 401 6ms

Обратите внимание, что "local strategy вызван" никогда не логируется.

Почему функция, которую я передал в LocalStrategy, не вызывается?

5 ответ(ов)

0

Недавно я столкнулся с данной проблемой, и она может быть вызвана несколькими причинами. Первым делом проверьте, настроен ли bodyParser для Express, и, как я вижу, вы это сделали:

app.use(express.bodyParser());

Следующим шагом убедитесь, что форма, которую вы отправляете на маршрут, содержит как username, так и password, и что пользователь заполняет оба поля. Я немного запутался, когда тестировал это, не вводя ничего в поле пароля 😃 Passport требует наличие обоих значений для выполнения функции проверки LocalStrategy, переданной в passport.authenticate('local').

Ваш пример также, похоже, правильно настроен для захвата как имени пользователя, так и пароля, но в любом случае стоит протестировать, правильно ли парсится тело запроса, даже без Passport:

app.post('/auth', function(req, res){
  console.log("парсинг тела", req.body);
  // должно быть что-то вроде: {username: ВАШ_ИМЯ_ПОЛЬЗОВАТЕЛЯ, password: ВАШ_ПАРОЛЬ}
});

В противном случае

Вы пробовали добавить обработчик запроса для вашего маршрута /auth?

app.post('/auth', passport.authenticate('local'), function(req, res){
  console.log("пользователь passport", req.user);
});

или

app.post('/auth', passport.authenticate('local', { successRedirect: '/', failureRedirect: '/auth' }));
0

Я столкнулся с той же проблемой, когда настраивал свой обработчик маршрутов, из которого вызывал passport.authenticate(). Я забыл, что passport.authenticate возвращает промежуточное ПО, которое нужно вызывать, поэтому просто вызов passport.authenticate недостаточен.

Я заменил следующий код:

router.post("/",
 function(req, res, next){
   passport.authenticate("local", function(err, user, info){

    // обработка успеха или неудачи

  }); 
})

на этот:

router.post("/",
 function(req, res, next){
   passport.authenticate("local", function(err, user, info){

    // обработка успеха или неудачи

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

Теперь маршрут работает правильно. Не забудьте вызывать возвращаемое промежуточное ПО!

0

Судя по всему, вы отправляете форму, не заполнив поле с именем пользователя или паролем. Если вы заполните оба поля и затем отправите форму, будет вызвана LocalStrategy.

0

Для Express 4.x вам нужно использовать middleware body-parser, чтобы обрабатывать входящие данные в формате application/x-www-form-urlencoded и application/json. Вот пример, как это сделать:

// Подключаем body-parser
var bodyParser = require('body-parser');

// Используем middleware для парсинга данных
app.use(bodyParser.urlencoded({ extended: false })); // парсим application/x-www-form-urlencoded
app.use(bodyParser.json()); // парсим application/json

Дополнительную информацию можно найти в репозитории body-parser на GitHub.

0

Я тоже долго мучился с аналогичной проблемой. У меня было все настроено, как советовали другие ответы:

  1. Форма возвращала все поля.
  2. Парсер тела (body parser) был правильно настроен с extended: true.
  3. Passport был сконфигурирован с учетом всех настроек.

Но я изменил поле username на phoneNumber и пароль. Изменив код следующим образом, я решил свою проблему:

passport.use('login', new LocalStrategy(
  { usernameField: 'phoneNumber', passwordField: 'password' },
  function (username, password, done) {
    // здесь ваша логика логина
  }
));

Если кому-то нужно, я могу написать всю процедуру аутентификации для телефона, используя MongoDB и passport-local.

Спасибо, @user568109!

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь