JSON Web Token 入门教程

官方
github

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;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值