Enzo学习:第8部分,使用JSON Web令牌实现API身份验证

我终于决定他妈的了,只是尝试保护我的API作为身份验证的第一步。 这是我今天(到目前为止)的承诺。

首先,我的代码基于JonathanMH的一个很棒的博客。 我添加了更多的依赖项,例如Passport,Passport-JWT和JWTWebtoken。

我使用JWTStrategy作为我的策略,并做了一条快速的登录路径来验证电子邮件和密码。 这是任何有兴趣的人的仓库。

因此,我声明了一种在用户模型中生成JWT的方法。 我不知道我做的是否正确,但是我试图使控制器更瘦,模型更胖。

我在使用过程中遇到了很多问题,例如缺少jwt变量。 因此,我回顾了module.exports工作方式,似乎我对该主题了解得很浅。 根据我的理解,我制作了一个文件,其中存放了我的所有护照和JWT模块。

我不知道我是否做对了,但是我还是尝试了。 在此过程中,我还发现了一个常见的Node.js错误,称为循环依赖 。 我几乎把头撞在桌子上,因为导出的模块未定义。 我发现自己正在覆盖模型中的自己的模块。 显然,我叫了两次,所以我做了一个小小的修改,将我的模型倒数第二(在我最终出口之前)。

  var jwt = require('jsonwebtoken'); var通行证= require(“ passport”); 
varpassportJWT = require(“ passport-jwt”);
var ExtractJwt =护照JWT.ExtractJwt;
var JwtStrategy =护照JWT.Strategy;
Exports.jwt = jwt;
Exports.passportJWT =护照JWT;
Export.ExtractJwt = ExtractJwt;
Exports.JwtStrategy = JwtStrategy;
exports.jwtOptions = {
jwtFromRequest:ExtractJwt.fromAuthHeaderWithScheme('bearer'),
secretOrKey:'tasmanianDevil'//修复:将其更改为env vars
};
var Users = require('../ models / users'); //仅在其他所有操作完成后才调用此函数,以免覆盖导出! Exports.strategy =新的JwtStrategy(this.jwtOptions,function(jwt_payload,next){
console.log('已收到有效载荷',jwt_payload);
Users.findById(jwt_payload.id,function(err,doc){
如果(err){res.send(err); }
如果(doc){
next(null,doc);
}其他{
next(null,false);
}
});
});
护照。使用(this.strategy);出口。护照=护照;

因此,我还重构了server.js,使其可以容纳护照。 和往常一样,我不确定自己是否做对了,

  const config = require('./ api / config'); 
const通行证= config.passport;
app.use(passport.initialize()); //一些代码... usersRoutes(app,护照);

现在我有了护照来验证请求,现在我将其实现为中间路线。

  //必须先走这条路线 
app.route('/ api / users / login')
.post(users.login);
app.route('/ secret')
.get(passport.authenticate('jwt',{session:false}),function(req,res){
res.json(“成功您可以看到我”);
});
app.route('/ api / users /:id')
.get(users.single)
.post(users.update)
.delete(users.delete);
app.route('/ api / profile')
.get(passport.authenticate('jwt',{session:false}),profile.get)
.post(passport.authenticate('jwt',{session:false}),profile.update);

我不知道是否有办法制作这种DRY,但是现在就可以了。 总比没有好,对吧?

无论如何,我也将头授权提取方案从JWT更改为Bearer。 主要是因为我看到OAuth使用Bearer作为前缀。 所以我只是为此做准备。 当然,这又是另一个猜测。 有人可以启发我吗?

  jwtFromRequest:ExtractJwt.fromAuthHeaderWithScheme(' bearer '), 

通过中间件中的所有检查后,我发现结果是传递了req.user对象。 因此,我为用户明确创建了一个新的控制器,并且将在JWT中的id有效负载的帮助下检索所有信息。 再一次,我不知道这在Node.js世界中是否很常见,但是我还是这么做了。 为了说明这一点,请查看此路线。

  '使用严格'; const mongoose = require('mongoose'); 
const Users = mongoose.model('Users');
exports.get = function(req,res){
res.json(
req.user ); //格式化字段
};
exports.update = function(req,res){
var params = req.body;
params.password = Users.hashPassword(params.password);
Users.findOneAndUpdate({_ idreq.user.id },{$ set:params},{new:true,runValidators:true,context:'query'},function(err,doc){
如果(err){res.send(err); }
res.json(doc);
});
};

无需在参数或请求正文中传递任何id,就已经基于中间件检查预先确定了id。

在研究了许多有关JWT和身份验证的内容之后,我发现特别是在实现JWT方面存在一些标准。 到期,正确的json有效负载,标头填充,刷新令牌等。 喔! 好厉害 但是我可能最终还是要这样做。

我现在将专注于JWT标准,这是我的下一步。

如果您正在阅读本文,则感谢您一路阅读! 下次见! 👋