无法使用 Passport 登录捕获 401 条件
Unable to catch a 401 condition using Passport login
我正在将 PassportJS 与 Local Strategy 和 passport-local-mongoose 结合使用。这是我的登录脚本:
// Configure Passport (server.js)
// ---------------------------------------------------------------
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// ---------------------------------------------------------------
.
// POST to /login (authenticate.js)
// ---------------------------------------------------------------
router.post('/login', (req, res) => {
// server-side validation
const errors = {
username: Validator.validateusername(req.body.username),
password: Validator.validatepassword(req.body.password),
};
if (!isEmpty(errors)) return res.send(JSON.stringify({ error: errors }));
passport.authenticate('local')(req, res, () => {
// If logged in, we should have user info to send back
if (req.user) {
const userdata = JSON.stringify(req.user);
const token = jwt.sign({
username: req.user.username,
firstName: req.user.firstName,
lastName: req.user.lastName,
email: req.user.email,
img: req.user.img,
}, process.env.JWT_SECRET);
res.cookie('token', token);
return res.send(userdata);
}
// Otherwise return an error
return res.send(JSON.stringify({ error: 'There was an error logging in' }));
});
});
这工作正常,除非出现登录错误。如果出于某种原因(401 或 500)登录失败,这个脚本 return 不应该是 There was an error logging in
消息吗?相反,它只是 return 一个 401 Unauthorized
?
此身份验证查找的模式是:
const { mongoose } = require('../config/dbconfig');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');
const User = new Schema({
username: {
type: String,
lowercase: true,
required: true,
unique: true,
},
password: {
type: String,
select: false,
required: true,
},
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
email: {
type: String,
lowercase: true,
required: true,
unique: true,
},
img: {
type: String,
},
}, { timestamps: true });
User.plugin(passportLocalMongoose);
module.exports = mongoose.model('User', User);
你说这个策略有点不对。您应该将它用作中间件,或者使用 custom callback way. Yours is a kind of mix between these - you call the strategy like it was a middleware but provide your own next
middleware function. Since authenticate is called as middleware but no failureRedirect
option is provided, Passport will return 401 by default. The next
function is called when successfully authenticated,在您的情况下,它不是下一个中间件,而是回调函数。
要使用自定义回调,您应该像这样编写路由处理程序:
app.post('/login', (req, res, next) => {
// ...
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err); }
if (user) {
// ...
req.login(user, (err) => {
if (err) { return next(err); }
return res.send(userdata);
});
} else {
return res.status(401).send({ error: 'There was an error logging in' });
}
})(req, res, next);
});
我正在将 PassportJS 与 Local Strategy 和 passport-local-mongoose 结合使用。这是我的登录脚本:
// Configure Passport (server.js)
// ---------------------------------------------------------------
passport.use(new LocalStrategy(User.authenticate()));
passport.serializeUser(User.serializeUser());
passport.deserializeUser(User.deserializeUser());
// ---------------------------------------------------------------
.
// POST to /login (authenticate.js)
// ---------------------------------------------------------------
router.post('/login', (req, res) => {
// server-side validation
const errors = {
username: Validator.validateusername(req.body.username),
password: Validator.validatepassword(req.body.password),
};
if (!isEmpty(errors)) return res.send(JSON.stringify({ error: errors }));
passport.authenticate('local')(req, res, () => {
// If logged in, we should have user info to send back
if (req.user) {
const userdata = JSON.stringify(req.user);
const token = jwt.sign({
username: req.user.username,
firstName: req.user.firstName,
lastName: req.user.lastName,
email: req.user.email,
img: req.user.img,
}, process.env.JWT_SECRET);
res.cookie('token', token);
return res.send(userdata);
}
// Otherwise return an error
return res.send(JSON.stringify({ error: 'There was an error logging in' }));
});
});
这工作正常,除非出现登录错误。如果出于某种原因(401 或 500)登录失败,这个脚本 return 不应该是 There was an error logging in
消息吗?相反,它只是 return 一个 401 Unauthorized
?
此身份验证查找的模式是:
const { mongoose } = require('../config/dbconfig');
const Schema = mongoose.Schema;
const passportLocalMongoose = require('passport-local-mongoose');
const User = new Schema({
username: {
type: String,
lowercase: true,
required: true,
unique: true,
},
password: {
type: String,
select: false,
required: true,
},
firstName: {
type: String,
required: true,
},
lastName: {
type: String,
required: true,
},
email: {
type: String,
lowercase: true,
required: true,
unique: true,
},
img: {
type: String,
},
}, { timestamps: true });
User.plugin(passportLocalMongoose);
module.exports = mongoose.model('User', User);
你说这个策略有点不对。您应该将它用作中间件,或者使用 custom callback way. Yours is a kind of mix between these - you call the strategy like it was a middleware but provide your own next
middleware function. Since authenticate is called as middleware but no failureRedirect
option is provided, Passport will return 401 by default. The next
function is called when successfully authenticated,在您的情况下,它不是下一个中间件,而是回调函数。
要使用自定义回调,您应该像这样编写路由处理程序:
app.post('/login', (req, res, next) => {
// ...
passport.authenticate('local', (err, user, info) => {
if (err) { return next(err); }
if (user) {
// ...
req.login(user, (err) => {
if (err) { return next(err); }
return res.send(userdata);
});
} else {
return res.status(401).send({ error: 'There was an error logging in' });
}
})(req, res, next);
});