我使用护照JWT进行身份验证,但是我无法运行回调函数/响应,仅当用户通过身份验证时才会运行。怎么办呢?
在我的路线中:
import express from 'express';
import passport from '../../config/passport';
import memberInfoCtrl from '../controllers/memberInfo';
const router = express.Router();
router.route('/members')
.get(membersCtrl.tokenCheck, passport.authenticate('jwt', { session: false }), membersCtrl.doSomethingElse);
export default router;
如果身份验证成功,我希望运行membersCtrl.doSomethingElse
。
这是我的tokenCheck功能:
function tokenCheck(req, res, next) {
const token = getToken(req.headers);
if (token) {
const decoded = jwt.decode(token, config.secret);
User.findOne({
email: decoded.email
}, (err, user) => {
if (err) throw err;
if (!user) {
return res.status(403).send({
success: false, msg: 'Authentication failed. User not found.'
});
}
// res.json({ success: true, msg: 'Welcome to the member area!' });
return next();
});
} else {
return res.status(403).send({ success: false, msg: 'No token provided.' });
}
}
在res.json
中使用tokenCheck
可以正常工作,但之后不会调用doSomethingElse
函数。
我认为这是因为我们发送了这样的回复:
res.json({ success: true, msg: 'Welcome to the member area!' });
用res.json
替换return next();
会返回错误:
Error: Unknown authentication strategy \"jwt\"
为什么会发生这种情况 - 如何在执行另一个功能之前检查身份验证,对于相同的路由?
我确定这是我想念的傻事。任何帮助表示赞赏!
这是我的主要快递脚本的一部分,初始化护照:
import passport from 'passport';
...
app.use(passport.initialize());
app.use('/api', routes);
...
护照配置:
const JwtStrategy = require('passport-jwt').Strategy;
import User from '../server/models/user';
import config from './env';
module.exports = (passport) => {
const opts = {};
opts.secretOrKey = config.secret;
passport.use(new JwtStrategy(opts, (jwtPayload, done) => {
User.findOne({ id: jwtPayload.id }, (err, user) => {
if (err) {
return done(err, false);
}
if (user) {
done(null, user);
} else {
done(null, false);
}
});
}));
};
答案 0 :(得分:3)
您的一般方法是正确的。要根据某些条件保护路由,请编写一个自定义中间件,如果满足这些条件,则调用next()
。
但在你的情况下,这不是必要的,因为这是passport-jwt
所做的。因此,假设您正确配置了passport
和passport-jwt
,您需要编写的是:
router.route('/members')
.get(passport.authenticate('jwt', { session: false }), membersCtrl.doSomethingElse);
passport-jwt
将从请求中提取JWT并根据您提供的密钥或密钥进行验证。然后,它将使用护照的verify
回调来填充req.user
(source)。
此外:使用res.json()
后发送了一个响应,这就是为什么你的护照中间件和其他任何东西都没有到达的原因。
关于您的错误Error: Unknown authentication strategy \"jwt\"
:如果您未正确配置护照身份验证,通常会发生这种情况。如果你把它包含在你的问题中,我会看一下并相应地扩展我的答案。
更新:您的代码看起来不错,除了一件事:您没有在jwtFromRequest
选项中指定passport-jwt
属性,这是强制性的。或者你有没有机会忘记调用你的护照配置?
更新2:有关我的评论的进一步说明:1。)导入您的ES6护照配置模块(您添加jwtFromRequest
选项的位置)在您的主快递脚本中并调用它:
import passport from 'passport';
import passportConfig from 'path/to/passport/config';
...
app.use(passport.initialize());
passportConfig(passport);
...
2。)确保删除tokenCheck
功能,但不需要它。请参阅此答案的第一部分。
更新3:'未经授权'很棒,因为这意味着您现在已成功保护/members
路线。要实施基于令牌的身份验证,您现在需要一条额外的路由/authenticate
,用户可以请求访问您的网络服务,例如通过提供凭据(您的路由将验证这些凭据并使用JWT进行响应,该JWT必须使用您用于passport-jwt
的相同秘密进行签名 - 否则passport-jwt
将无法在稍后验证令牌签名)
但这超出了这个问题的范围。应该有很多资源可以解决这个问题。例如,您可以使用jsonwebtoken
中的/authenticate
实现passport
路由({3}}(他们根本不使用jsonwebtoken
,但使用Route::resource('users', 'UsersController');
进行令牌创建< em>和验证)。
注意:如果您还要实现客户端,则必须在其中包含一些额外的逻辑来存储JWT并将其包含在您对快速应用程序的请求中。