加密语法:
jsonwebtoken.sign(payload, secretOrPrivateKey, [options, callback]);
payload
必须是一个object, buffer或者string,用来保存一些信息。
secretOrPrivateKey
是包含HMAC算法的密钥或RSA和ECDSA的PEM编码私钥的string或buffer。
options
包括以下选项:
- itemalgorithm:加密算法(默认值:HS256)
- expiresIn:以秒表示或描述时间跨度zeit / ms的字符串。如60,“2 days”,“10h”,“7d”, -Expiration time,过期时间
- notBefore:定义在什么时间之前,该jwt都是不可用的。以秒表示或描述时间跨度zeit / ms的字符串。如:60,“2days”,“10h”,“7d”
- audience
- issuer:jwt签发者
- jwtid: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
- subject:jwt所面向的用户
- noTimestamp
- header
Usage
1. 安装jwt依赖
npm:
npm i jsonwebtoken
yarn:
yarn add jsonwebtoken
2. 生成密钥
# 终端中输入OpenSSl,进入openssl
OpenSSL
OpenSSL>genrsa -out jwt.pem 1024
OpenSSl>rsa -in jwt.pem -pubout -out jwt_pub.pem
会生成两个文件:jwt.pem、jwt_pub.pem
3. 登陆接口生成token
user.js
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
const _C = require('./constants');
// ...
Router.post('/login', (req, res) => {
const { username, pwd } = req.body;
User.findOne({ username }, (err, doc) => {
if (err) throw err;
// 用户不存在
if (!doc) {
return res.json(_C.CODE_NO_USER);
} else {
// 密码错误
// # 简化的代码,没有密码加密存储
if (pwd !== doc.pwd) return res.json(_C.CODE_ERROR_PWD);
// 验证通过生成 token
const cert = fs.readFileSync(path.resolve(__dirname, '../lib/jwt.pem'));
const token = jwt.sign({
user: doc.username,
id: doc._id
}, cert, {
algorithm: 'RS256', // 加密算法(默认值:HS256)
expiresIn: '1h', // 过期时间
});
return res.json({
..._C.CODE_SUCCESS,
data: { token }
});
}
});
});
到这里一个token
就已经生成了。
4. 定义解密token的中间件
定义一个校验方法,用来当作中间件,方便使用。
utils.js
const path = require('path');
const jwt = require('jsonwebtoken');
const _C = require('./constants');
// ...
function authtoken (req, res, next) {
const token = req.cookies.token;
if (token) {
const cert = fs.readFileSync(path.resolve(__dirname, './jwt_pub.pem'));
jwt.verify(token, cert, (err, decoded) => {
// token失效
if (err) {
res.json(_C.CODE_PERMISSION_DENIED);
} else {
// 放行
req.userinfo = decoded;
next();
}
});
// 未登陆
} else {
res.json(_C.CODE_NO_LOGIN);
}
}
5. 在需要的接口中加入token校验
直接在接口的定义中加入中间件即可。
user.js
const _U = require('../lib/utils');
// ...
// get user info
Router.post('/info', _U.authtoken, (req, res) => {
const userinfo = req.userinfo;
User.findOne({ username: userinfo.user }, (err, doc) => {
if (err) throw err;
if (!doc) {
return res.json(_C.CODE_NO_USER);
} else {
return res.json({
..._C.CODE_SUCCESS,
data: {
name: doc.username,
user_id: doc.username,
access: [doc.type]
}
});
}
});
});