我正在尝试通过Passport.js在本地对用户进行身份验证,同时又不保留会话并使用自己的JWToken。
我正在关注本教程: Learn using JWT with Passport authentication
同时也阅读Passport.js文档。我不知道出了什么问题,但是护照似乎并没有注意到某些功能确实是功能。
我有一个加载功能,可以根据特定条件从数据库(mongo)中选择一个用户(用户可以使用电子邮件或电话号码登录)。
load: function(options, cb) {
options.select = options.select || 'email phone';
return this.findOne(options.criteria)
.select(options.select)
.exec(cb);
}
我正在打电话给我的护照。请在我的路线中进行身份验证:
// Controllers //
const Users = require('../../app/controllers/users');
...
...
app.post('/api/login', passport.authenticate('local', { failureRedirect: '/api/login' }), Users.login);
这是我的本地策略:
const mongoose = require('mongoose');
const User = mongoose.model('User');
const passport = require('passport');
const LocalStrategy = require('passport-local').Strategy;
passport.use(new LocalStrategy(
{
usernameField: 'email',
phoneField: 'phone',
passwordField: 'password',
session: false
},
function(email, phone, password) {//cb == callback
const options = {
criteria: { email: email, phone: phone },
select: 'name username email hashed_password salt'
};
User.load(options, function(err, user) {
if (err || !user){
return res.status(400).json({
type: 'failure',
message: "User creation failed",
data: [err]
});
};
if (!user.authenticate(password)) {
return res.status(400).json({
type: 'failure',
message: "User creation failed",
data: [err]
});
};
req.login(user, {session: false}, (err) => {
if (err) {
res.send(err);
}
// generate a signed son web token with the contents of user object and return it in the response
const token = jwt.sign(user.id, 'your_jwt_secret');
return res.json({user, token});
});
});
}
));
我遇到以下错误:
TypeError: res.status is not a function
在尝试与被申请人从护照取回东西之前。我曾尝试像本教程中那样使用cb(callback)来做到这一点,但是我仍然遇到相同的错误。
在此先感谢您的帮助!
答案 0 :(得分:0)
在实施Passport的本地策略时会遇到一些问题,这会引起问题。
当Passport的本地启动方式仅接受一个字段时,您尝试使用两个字段作为用户名。 (请参阅:http://www.passportjs.org/packages/passport-local/)
function(username, password, done){}
如果您想同时使用它们作为用户名,则可能需要考虑创建自己的自定义策略。这将进行更深入的介绍,但是您可以在Passport Github页面(https://github.com/jaredhanson/passport-strategy)上开始学习
第二个问题是您正在尝试让Passport在本地策略中发送响应,这不是本来打算做的。相反,您应该将错误传递并返回值到Passport的done()
函数,该函数将对其进行相应的处理。
以下是您的本地策略应为以下示例:
passport.use(
new LocalStrategy(async (email, phone, password, done) => {
const options = {
criteria: { email, phone },
select: 'name username email hashed_password salt',
};
try {
const user = await User.load(options);
/**
* If null is returned meaning there was no user found, send the done call
* with the false flag. This tells passport to redirect to the failure URL.
*/
if (!user) {
return done(null, false);
}
/**
* If the user's password is incorrect, also return the done function with the false
* flag. This tells passport to redirect to the failure URL.
*/
if (!user.authenticate(password)) {
return done(null, false);
}
/**
* If a user is found and their password is verified, send the user object to
* the done function. This will tell Passport to call the next middelware attaching
* the user object.
*/
return done(null, user);
} catch (err) {
/**
* If there is an error with the DB call, return generic message
* for security purposes.
*/
return done('There was an internal server error.');
}
})
);
以及加载函数应如下所示的示例:
load: options => {
return new Promise(async (resolve, reject) => {
options.select = options.select || 'email phone';
try {
const user = await this.findOne(options.criteria)
.select(options.select)
.exec();
resolve(user);
} catch (err) {
reject(err);
}
});
};
作为一般的最佳实践,我将您的回调更改为较新的Promise方法(https://developers.google.com/web/fundamentals/primers/promises)。
这应该以您打算使用Passport的方式工作。