jwt的使用

发表于:2017-09-04

什么是JWT

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准.该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjU5YWFlOTYxNGE2YzNkNTM0Nzg3OTQzNyIsIm5pY2tuYW1lIjoi5Y2w5bqm5aSn5L2_IiwidXNlcm5hbWUiOiJ4amgyMjIyMjIyOCIsImxldmVsIjowLCJpYXQiOjE1MDQ1MTUyOTksImV4cCI6MTUwNTEyMDA5OX0.dObflyFZqENR9K3ftRNfWqMUQOZf_XzrknzOxxm6hsM

JWT的构成

第一部分我们称它为头部(header),第二部分我们称其为载荷(payload),第三部分是签名

接下来看看如何使用jwt

先安装jsonwebtoken

npm install jsonwebtoken --save

var jwt = require('jsonwebtoken')
// 一共3个有用的方法, jwt.sign()、jwt.verify()、jwt.decode()
jwt.sigin() 的使用
// 一共4个参数, 第一个是payload, 第二个参数是签名, 第三个参数可选是一些配置项, 第4个参数是回调(err, token),2个参数(可选)
var token = jwt.sign({ username: 'xiejiahe' }, 'secret', {
    expiresIn: 60*60*24,      // 过期时间, 秒payload简写:exp
    notBefore: 50,              // 签发之前不能用, 50秒之前不能用payload简写nbf
    algorithm: 'HS256',          // 默认是HS256加密,一般不改。
    issuer: 'jwt签发者',        // 签发着谁签发,选填,payload简写:iss
    audience: '接收jwt的一方',  // 谁接收,选填, payload简写:aud
    jwtid: 'jwt的唯一身份标识',  // 主要用来作为一次性token,从而回避重放攻击。payload简写:jti
});
console.log(token);
输出:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InhpZWppYWhlIiwiaWF0IjoxNTA0NTE2NTY3LCJuYmYiOjE1MDQ1MTY2MTcsImV4cCI6MTUwNDYwMjk2NywiYXVkIjoi5o6l5pS2and055qE5LiA5pa5IiwiaXNzIjoiand0562-5Y-R6ICFIiwianRpIjoiand055qE5ZSv5LiA6Lqr5Lu95qCH6K-GIn0.cd5TK_npO0gOXhVANIHOPucZe8_edzZMAp1DSoHh3Fo
//
//  或者用回调。 由于签发时间不一样结果都一样。
jwt.sign({ username: 'xiejiahe' }, 'secret', {
    expiresIn: 60*60*24,      // 过期时间, 秒payload简写:exp
    notBefore: 50,              // 签发之前不能用, 50秒之前不能用payload简写nbf
    algorithm: 'HS256',          // 默认是HS256加密,一般不改。
    issuer: 'jwt签发者',        // 签发着谁签发,选填,payload简写:iss
    audience: '接收jwt的一方',  // 谁接收,选填, payload简写:aud
    jwtid: 'jwt的唯一身份标识',  // 主要用来作为一次性token,从而回避重放攻击。payload简写:jti
}, (err, token) => {
    console.log(token)
});

// 要注意的是payload不要存放敏感信息 比如密码。 签名要保管好相当于是你的密码
// 第三个参数配置的简写可以在payload配置,比如
// 看个人喜好用哪一种。
jwt.sign({ 
    username: 'xiejiahe',
    exp: 60*60*24,
    nbf: 50,
    iss: 'jwt签发者',
}, 'secret', (err, token) => {
    console.log(token)
});
输出:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InhpZWppYWhlIiwiZXhwIjo4NjQwMCwibmJmIjo1MCwiaXNzIjoiand0562-5Y-R6ICFIiwiaWF0IjoxNTA0NTE3MDM1fQ.L6rPzdsEinw9vSAU2oUIHCUmWQ2_OrQlUbLjUHSt1Ho

接下来看看如何验证token

// jwt.verify()的使用
// 记得要用try catch 否则捕获不了错误。  第一个参数是token, 就是上面签发的token,第二个是签名。
// 第一种解密方式。
try {
    var decoded = jwt.verify(token, 'secret');
    console.log(decoded);
} catch (e) {
    console.log(e);
}
//
// 第二种,回调方式
jwt.verify(token, 'secret', (err, decoded) => {
    if( err ) {
        console.log('token 无法验证');
    }
    console.log(decoded);
});
输出:

{ username: 'xiejiahe',
  iat: 1504517338,     // 签发时间, 其他的看前面
  nbf: 1504517388,
  exp: 1504603738,
  aud: '接收jwt的一方',
  iss: 'jwt签发者',
  jti: 'jwt的唯一身份标识' }

// 很多人会这么判断 , 其实不需要判断过期时间, 因为过期了根本验证不了。所以略过这一步
jwt.verify(token, 'secret', (err, decoded) => {
    if( decoded.exp < new Date() / 1000 ) {
        console.log('过期...')
    }
});

**解码token**
// jwt.decode()的使用
var decode = jwt.decode(token)
console.log(decode);
输出:
{ username: 'xiejiahe',
  iat: 1504517338,
  nbf: 1504517388,
  exp: 1504603738,
  aud: '接收jwt的一方',
  iss: 'jwt签发者',
  jti: 'jwt的唯一身份标识' }
// 这个是解码token, 并不是验证,不是很常用。
//
//

最后要说的是保管好签名, payload 不应该存放敏感信息。 jwt是通用性的,Node.js、PHP、Java等很多语言都可以用。

Node.js