当在 passport.js 登录周期中创建完全缺少凭据错误时
when exactly missing credentials error created in passport.js login cycle
我决定使用 passport.js 对我的节点应用程序进行身份验证。我实施了登录和注册的本地策略,它们工作正常,但有一个问题让我感到困惑。我过去构建了一个模块,它使用 http-error 包生成 returns http 错误。我用它来标准化错误生成。例如,如果某些凭据丢失或无效,我会致电
Errors.ValidationError({name:"password",reason:"password field is missing in your request"})
这会创建并 returns 正确的 http 错误,我将其发送给用户。它对于错误生成很有用。我想将此逻辑与护照一起使用,因此我选择创建自己的回调。这是一些代码:
本地登录策略定义
/**
* User login
* @param {*} request
* @param {*} response
* @return {*} logged existant user or error
*/
passport.use('login',
new localStrategy(
{
usernameField: 'email',
passwordField: 'password',
},
async (email, password, done)=> {
if(email==null||password==null)
{
AppLogger.debug(21)
return done(null, false);
}
User.findOne({ email: email }).
then(async(user)=>{
if (!user) {
AppLogger.debug(22)
return done(null, false);
}
if (!(await user.verifyPassword(password))) {
AppLogger.debug(23)
return done(null, false);
}
return done(null, user);
}).
catch((err)=>{
AppLogger.debug(24)
return done(err);
});
}
)
);
登录路径
/**
* Login an existant user
*/
AuthRouter.post('/login', (req, res, next)=> {
passport.authenticate('login', (err, user, info) =>{
if (err) {
AppLogger.debug(1)
return next(err);
}
if (!user) {
AppLogger.debug(2)
return next(info);
}
req.login(user,(err)=>{
if(err){
AppLogger.debug(3)
return next(err);
}
res.send({
success:true,
message:"logged in"
})
})
})(req, res, next);
});
考虑到代码中的所有调试行,我得到了这个输出:
logs
我的日志行打印 2,这意味着没有异常,但用户为空,我试图了解在登录策略中确切创建了缺少凭据错误的位置,以便我可以生成自定义 http 错误。奇怪的是 none 策略中的调试没有被执行。请注意,有一个中间件可以捕获所有错误和日志,因此错误日志来自那里。并且保持实物应用程序按预期工作,但我无法发现此错误的产生位置。我假设护照中间件中的某些方法抛出错误,我的日志中间件捕获了它,但我如何与它交互并以有意义的方式生成我的 http 错误?任何建议表示赞赏。
这是我想出的解决方法:
路由器
/**
* Login an existant user
*/
AuthRouter.post('/login', (req, res, next)=> {
if(!req.body.email || !req.body.password){
const subErrors = []
if(!req.body.email){
subErrors.push({
name:"email",
reason:"login request must contain email"
})
}
if(!req.body.password){
subErrors.push({
name:"password",
reason:"login request must contain password"
})
}
const httpError = Errors.ValidationError(subErrors);
return next(httpError);
}
passport.authenticate('login', (err, user, info) =>{
if (err) {
return next(err);
}
if (!user) {
return next(info);
}
req.login(user,(err)=>{
if(err){
return next(err);
}
res.send({
success:true,
message:"logged in"
})
})
})(req, res, next);
});
由于最终目标是用我的自定义 http 错误替换 passport 的默认丢失凭据错误,而且我在 passportjs 策略中找不到方法,所以我在调用 passport.authenticate()
之前检查了请求正文
我可以成功创建并 return 我的自定义错误,但这意味着尽管我手动检查,passportjs 也会检查凭据是否存在。所以它不是最佳的性能。
我也知道使用
if(x===null)
在某些情况下会导致一些问题,我也在原始代码中使用了'=='而不是'==='。它与主要问题无关,但不是最佳实践。
最后是默认和自定义错误响应:
这就是passportjs returns
{"message":"Missing credentials"}
这是我的自定义错误
{
"statusCode":400,
"error":"Bad Request",
"invalid_params":[
{
"name":"password",
"reason":"login request must contain password"
}
],
"type":"about:blank",
"title":"invalid parameters"}
我希望我能很好地解释我想要实现的目标。现在一切都按预期工作,但正如我所说的这个逻辑,我正在检查同一件事两次,所以如果有更好的解决方案,我们将不胜感激。
我决定使用 passport.js 对我的节点应用程序进行身份验证。我实施了登录和注册的本地策略,它们工作正常,但有一个问题让我感到困惑。我过去构建了一个模块,它使用 http-error 包生成 returns http 错误。我用它来标准化错误生成。例如,如果某些凭据丢失或无效,我会致电
Errors.ValidationError({name:"password",reason:"password field is missing in your request"})
这会创建并 returns 正确的 http 错误,我将其发送给用户。它对于错误生成很有用。我想将此逻辑与护照一起使用,因此我选择创建自己的回调。这是一些代码:
本地登录策略定义
/**
* User login
* @param {*} request
* @param {*} response
* @return {*} logged existant user or error
*/
passport.use('login',
new localStrategy(
{
usernameField: 'email',
passwordField: 'password',
},
async (email, password, done)=> {
if(email==null||password==null)
{
AppLogger.debug(21)
return done(null, false);
}
User.findOne({ email: email }).
then(async(user)=>{
if (!user) {
AppLogger.debug(22)
return done(null, false);
}
if (!(await user.verifyPassword(password))) {
AppLogger.debug(23)
return done(null, false);
}
return done(null, user);
}).
catch((err)=>{
AppLogger.debug(24)
return done(err);
});
}
)
);
登录路径
/**
* Login an existant user
*/
AuthRouter.post('/login', (req, res, next)=> {
passport.authenticate('login', (err, user, info) =>{
if (err) {
AppLogger.debug(1)
return next(err);
}
if (!user) {
AppLogger.debug(2)
return next(info);
}
req.login(user,(err)=>{
if(err){
AppLogger.debug(3)
return next(err);
}
res.send({
success:true,
message:"logged in"
})
})
})(req, res, next);
});
考虑到代码中的所有调试行,我得到了这个输出: logs
我的日志行打印 2,这意味着没有异常,但用户为空,我试图了解在登录策略中确切创建了缺少凭据错误的位置,以便我可以生成自定义 http 错误。奇怪的是 none 策略中的调试没有被执行。请注意,有一个中间件可以捕获所有错误和日志,因此错误日志来自那里。并且保持实物应用程序按预期工作,但我无法发现此错误的产生位置。我假设护照中间件中的某些方法抛出错误,我的日志中间件捕获了它,但我如何与它交互并以有意义的方式生成我的 http 错误?任何建议表示赞赏。
这是我想出的解决方法:
路由器
/**
* Login an existant user
*/
AuthRouter.post('/login', (req, res, next)=> {
if(!req.body.email || !req.body.password){
const subErrors = []
if(!req.body.email){
subErrors.push({
name:"email",
reason:"login request must contain email"
})
}
if(!req.body.password){
subErrors.push({
name:"password",
reason:"login request must contain password"
})
}
const httpError = Errors.ValidationError(subErrors);
return next(httpError);
}
passport.authenticate('login', (err, user, info) =>{
if (err) {
return next(err);
}
if (!user) {
return next(info);
}
req.login(user,(err)=>{
if(err){
return next(err);
}
res.send({
success:true,
message:"logged in"
})
})
})(req, res, next);
});
由于最终目标是用我的自定义 http 错误替换 passport 的默认丢失凭据错误,而且我在 passportjs 策略中找不到方法,所以我在调用 passport.authenticate()
之前检查了请求正文
我可以成功创建并 return 我的自定义错误,但这意味着尽管我手动检查,passportjs 也会检查凭据是否存在。所以它不是最佳的性能。
我也知道使用
if(x===null)
在某些情况下会导致一些问题,我也在原始代码中使用了'=='而不是'==='。它与主要问题无关,但不是最佳实践。
最后是默认和自定义错误响应:
这就是passportjs returns
{"message":"Missing credentials"}
这是我的自定义错误
{
"statusCode":400,
"error":"Bad Request",
"invalid_params":[
{
"name":"password",
"reason":"login request must contain password"
}
],
"type":"about:blank",
"title":"invalid parameters"}
我希望我能很好地解释我想要实现的目标。现在一切都按预期工作,但正如我所说的这个逻辑,我正在检查同一件事两次,所以如果有更好的解决方案,我们将不胜感激。