关于 nodejs 里面的 jwt
关于token
为什么要用token?
对于传统的session,客户端做一次记录,以方便用户下次请求的鉴别,通常而言session都是保存在内存中,而随着认证用户的增多,服务端的开销会明显增大。
传统session存储的扩展性差,服务端做认证记录,如果认证的记录被保存在内存中的话,这意味着用户下次请求还必须要请求在这台服务器上,这样才能拿到授权的资源,这样在分布式的应用上,相应的限制了负载均衡器的能力。这也意味着限制了应用的扩展能力。
传统session的安全性差, cookie如果被截获,用户就会很容易受到跨站请求伪造的攻击(csrf)
token
基于token的鉴权机制类似于http协议是无状态的,它不需要在服务端去保留用户的认证信息或者会话信息。这就意味着基于token认证机制的应用不需要去考虑用户在哪一台服务器登录了,这就为应用的扩展提供了便利。
流程上是这样的:
-
用户使用用户名密码来请求服务器
-
服务器进行验证用户的信息
-
服务器通过验证发送给用户一个token
-
客户端存储token,并在每次请求时附送上这个token值
-
服务端验证token值,并返回数据
这个token必须要在每次请求时传递给服务端,它应该保存在请求头里, 另外,服务端要支持CORS(跨来源资源共享)策略,一般我们在服务端这么做就可以了Access-Control-Allow-Origin: *。
一个token由三部分组成。
第一部分我们称它为头部(header),第二部分我们称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).
Express中jwt的定义方式:
在用户验证的文件中,颁发jwt,设定规则,私钥和有效期:jwt规定token前要加Bearer标注
const rule = {
id: user.id,
email: user.email,
name: user.name
};
const key = keys.secretOrKey;
jwt.sign(rule,key,{expiresIn: 3600},(err,token)=>{
res.json({
success: true,
token: "Bearer " + token
})
}).catch(err => {
return err;
});
验证jwt
服务器文件中初始化passport,并将其作为参数传入passport的配置目录
const passport = require("passport");
// 初始化passport
app.use(passport.initialize());
// 把passport传入passport文件
require("./config/passport")(passport);
在passport的配置文件中配置token验证的方式为jwt验证
const JwtStrategy = require("passport-jwt").Strategy,
ExtractJwt = require("passport-jwt").ExtractJwt;
// 读取数据库以便后面验证是否有相应userid对应的token
const mongoose = require("mongoose");
const User = mongoose.model("users");
const keys = require("../config/keys");
const opts = {};
// 配置passport支持jwt
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = keys.secretOrKey;
// 导出passport-jwt
module.exports = (passport) => {
passport.use(
new JwtStrategy(opts, (jwt_payload, done) => {
// 查看是否有该id生成的jwt
User.findOne({_id: jwt_payload.id}, (err, user) => {
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
});
})
);
};
在用户管理文件中引入配置好的passport
// 检测登录状态
// $route GET api/users/current
// @desc 返回当前登录的用户
// @access private
// 地址 验证token 回调函数
router.get("/current",passport.authenticate('jwt',{session:false}),
(req,res)=>{
res.json({
id: req.user.id,
email: req.user.email,
name: req.user.name
});
});
这主要是笔记

浙公网安备 33010602011771号