Стратегия локальной аутентификации Passport не вызывается
Я, конечно, упустил что-то очевидное, но не могу разобраться. Функция, которую я передал конструктору 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 ответ(ов)
Недавно я столкнулся с данной проблемой, и она может быть вызвана несколькими причинами. Первым делом проверьте, настроен ли 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' }));
Я столкнулся с той же проблемой, когда настраивал свой обработчик маршрутов, из которого вызывал 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);
})
Теперь маршрут работает правильно. Не забудьте вызывать возвращаемое промежуточное ПО!
Судя по всему, вы отправляете форму, не заполнив поле с именем пользователя или паролем. Если вы заполните оба поля и затем отправите форму, будет вызвана LocalStrategy.
Для 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.
Я тоже долго мучился с аналогичной проблемой. У меня было все настроено, как советовали другие ответы:
- Форма возвращала все поля.
- Парсер тела (body parser) был правильно настроен с extended: true.
- Passport был сконфигурирован с учетом всех настроек.
Но я изменил поле username на phoneNumber и пароль. Изменив код следующим образом, я решил свою проблему:
passport.use('login', new LocalStrategy(
{ usernameField: 'phoneNumber', passwordField: 'password' },
function (username, password, done) {
// здесь ваша логика логина
}
));
Если кому-то нужно, я могу написать всю процедуру аутентификации для телефона, используя MongoDB и passport-local.
Спасибо, @user568109!
Ошибка "npm WARN package.json: Нет поля repository"
Как получить параметры GET после "?" в Express?
Включение HTTPS в express.js
Express 4: Middleware для обработки ошибок не вызывается
Как вернуть результаты Mongoose из метода find?