nodejs 安装 jwt
npm install jsonwebtoken
生成token
使用格式: jwt.sign(payload, secretOrPrivateKey, [options, callback])
异步函数callback 是err 和jwt
同步函数返回 sonWebToken 字符串
payload 可以是表示有效JSON的对象文本、缓冲区或字符串。
secretOrPrivateKey 秘钥
options 选项:
algorithm(默认值:HS256)
expiresIn:以秒表示或描述时间跨度zeit / ms的字符串。
如:60,"2 days","10h","7d"。数值被解释为秒数。如果使用字符串,请确保提供时间单位(天,小时等),否则默认使用毫秒单位("120"等于"120ms")。
notBefore:以秒表示或描述时间跨度zeit / ms的字符串。
如:60,"2 days","10h","7d"。数值被解释为秒数。如果使用字符串,请确保提供时间单位(天,小时等),否则默认使用毫秒单位("120"等于"120ms")。
audience
issuer
jwtid
subject
noTimestamp
header
keyid
mutatePayload:如果为true,则sign函数将直接修改有效负载对象。如果在应用声明之后但在将其编码为令牌之前需要对有效内容的原始引用,这将非常有用。
默认同步签名(HMAC SHA256)
var jwt = require('jsonwebtoken');
var token = jwt.sign({ foo: 'bar' }, 'shhhhh');
使用RSA SHA256进行同步签名
// sign with RSA SHA256
var privateKey = fs.readFileSync('private.key');
var token = jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256'});
异步签名
jwt.sign({ foo: 'bar' }, privateKey, { algorithm: 'RS256' }, function(err, token) {
console.log(token);
});
回溯一个jwt 30秒
var older_token = jwt.sign({ foo: 'bar', iat: Math.floor(Date.now() / 1000) - 30 }, 'shhhhh');
签署一小时到期的token
jwt.sign({
exp: Math.floor(Date.now() / 1000) + (60 * 60),
data: 'foobar'
}, 'secret');
签署一小时到期的token 的另外的方式
jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: 60 * 60 });
//or even better:
jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: '1h' });
服务端使用
验证
格式: jwt.verify(token, secretOrPublicKey, [options, callback])
options
algorithms:包含允许的算法名称的字符串列表。例如,["HS256", "HS384"]。
audience:如果要查看audience(aud),请在此处提供值。可以根据字符串,正则表达式或字符串和/或正则表达式列表来检查受众。
如:"urn:foo",/urn:f[o]{2}/,[/urn:f[o]{2}/, "urn:bar"]
complete:返回具有已解码的对象,{ payload, header, signature }而不是仅返回有效负载的常用内容。
issuer(可选):iss字段的有效值字符串或字符串数组。
ignoreExpiration:如果true不验证令牌的到期时间。
ignoreNotBefore...
subject:如果要检查subject(sub),请在此处提供值
clockTolerance:检查nbf和exp声明时可以容忍的秒数,以处理不同服务器之间的小时钟差异
maxAge:令牌的最大允许年龄仍然有效。它以秒表示或描述时间跨度zeit / ms的字符串。
如:1000,"2 days","10h","7d"。数值被解释为秒数。如果使用字符串,请确保提供时间单位(天,小时等),否则默认使用毫秒单位("120"等于"120ms")。
clockTimestamp:应该用作所有必要比较的当前时间的秒数。
nonce:如果要检查nonce声明,请在此处提供字符串值。它用于ID令牌的Open ID。(开放ID实施说明)
验证方法
// verify a token symmetric - synchronous
var decoded = jwt.verify(token, 'shhhhh');
console.log(decoded.foo) // bar
// verify a token symmetric
jwt.verify(token, 'shhhhh', function(err, decoded) {
console.log(decoded.foo) // bar
});
// invalid token - synchronous
try {
var decoded = jwt.verify(token, 'wrong-secret');
} catch(err) {
// err
}
// invalid token
jwt.verify(token, 'wrong-secret', function(err, decoded) {
// err
// decoded undefined
});
// verify a token asymmetric
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, function(err, decoded) {
console.log(decoded.foo) // bar
});
// verify audience
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo' }, function(err, decoded) {
// if audience mismatch, err == invalid audience
});
// verify issuer
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer' }, function(err, decoded) {
// if issuer mismatch, err == invalid issuer
});
// verify jwt id
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid' }, function(err, decoded) {
// if jwt id mismatch, err == invalid jwt id
});
// verify subject
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { audience: 'urn:foo', issuer: 'urn:issuer', jwtid: 'jwtid', subject: 'subject' }, function(err, decoded) {
// if subject mismatch, err == invalid subject
});
// alg mismatch
var cert = fs.readFileSync('public.pem'); // get public key
jwt.verify(token, cert, { algorithms: ['RS256'] }, function (err, payload) {
// if token alg != RS256, err == invalid signature
});
// Verify using getKey callback
// Example uses https://github.com/auth0/node-jwks-rsa as a way to fetch the keys.
var jwksClient = require('jwks-rsa');
var client = jwksClient({
jwksUri: 'https://sandrino.auth0.com/.well-known/jwks.json'
});
function getKey(header, callback){
client.getSigningKey(header.kid, function(err, key) {
var signingKey = key.publicKey || key.rsaPublicKey;
callback(null, signingKey);
});
}
jwt.verify(token, getKey, options, function(err, decoded) {
console.log(decoded.foo) // bar
});
解密
格式 jwt.decode(token [, options])
options:
- json: force JSON.parse on the payload even if the header doesn’t contain “typ”:“JWT”.
- complete: return an object with the decoded payload and header.
// get the decoded payload ignoring signature, no secretOrPrivateKey needed
var decoded = jwt.decode(token);
// get the decoded payload and header
var decoded = jwt.decode(token, {complete: true});
console.log(decoded.header);
console.log(decoded.payload)
Successful examples
// 引入模块依赖
const fs = require('fs');
const path = require('path');
const jwt = require('jsonwebtoken');
// 创建 token 类
class Jwt {
constructor() {
}
//生成token
generateToken(data) {
let created = Math.floor(Date.now() / 1000);
let cert = fs.readFileSync(path.join(__dirname, 'rsa_private_key.pem'));//私钥 可以自己生成
let token = jwt.sign({
data,
exp: created ,//+ 60 * 30
}, cert, {algorithm: 'RS256'});//sha256 RS256
return token;
}
// 校验token
verifyToken(token) {
let cert = fs.readFileSync(path.join(__dirname, 'rsa_public_key.pem'));//公钥 可以自己生成
let res;
try {
let result = jwt.verify(token, cert, {algorithms: ['RS256']}) || {};
let {exp = 0} = result, current = Math.floor(Date.now() / 1000);
if (current <= exp) {
res = result.data || {};
}
} catch (e) {
console.log(e.message);
return false;
}
return res;
}
decodeToken(token){
let decoded = jwt.decode(token, {complete: true});
return decoded;
}
}
module.exports = Jwt;