jwt 就是这么简单

文章不保证最新,最新版请到博客 www.huborui.com 查看。

JSON Web Token 是一个非常简单实用的规范,通过它可以在客户端和服务端之前传递安全可靠的数据。

jwt 由三部分组成:

  • 头部(header)
  • 载荷(payload)
  • 签名(signature)

将这三部分用 . 连接起来就构成一个 jwt(header.payload.signature)。

下面就通过这三个部分道出从 jwt 生成到获取数据的原理。

header

header 描述 jwt 的基本信息,如类型、签名所用算法等。

{
    // 类型为 JWT
    "typ": "JWT",
    // HS256 算法
    "alg": "HS256"
}
复制代码

对 header 进行 Base64 编码,得到第一部分。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
复制代码

没错,Base64 编码并不是加密方式,可以还原的!不加密我们的 jwt 还安全么?继续看下去。

payload

payload 是携带数据的地方,我们可以将需要传递到服务端的数据放在 payload 内。

既然我们的宝贝数据放在 payload,那它会不会被加密?

不会!还是 Base64 编码,可以还原的!所以不要往里面放贵重的数据。

{
    // 官方定义了 5 个字标识一些信息
    // jwt 签发者
    "iss": "god",
    // 在什么时候签发 
    "iat": 1441525213,
    // exp 什么时候过期 Unix 时间戳
    "exp": 1441525324,
    // 接收 jew 的用户
    "aud": "[email protected]"
    // jwt 面向的用户
    "sub": "[email protected]"
    // 剩下的就可以自己定义了
    "userID": 12345,
    ...
}
复制代码

依旧 Base64 编码,得到第二部分的字符串和 header 用 . 拼在一起。

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0
复制代码

别急,是不是觉得都是明文的数据,服务器如何判断 jwt 的真假呢?下面就到了签名加密环节。

signature

在签名环节,我们需要提供一个只有你知道的密钥(secret),对连在一起的 header 和 payload 用 HS256 算法加密,得到加密后的字符串,和前面的拼在一起:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmcm9tX3VzZXIiOiJCIiwidGFyZ2V0X3VzZXIiOiJBIn0.rSWamyAYwuHCo7IFAgd1oRpSP7nzL7BF5t7ItqpKViM
复制代码

三部分合体成功!jwt 构造成功!

防伪

是否能伪造 jwt 呢?仔细想想就知道,如果你不知道服务端的密钥,手动修改 header 或 payload 的任何部分,得到的 Base64 编码就不一样了,新的编码经过密钥生成的签名肯定和旧的不同。没有正确的签名,服务器会直接返回错误。

服务器验证一个 jwt 的过程也很简单:

  1. 收到 jwt
  2. 将 header 和 payload 用密钥和对应的算法签名
  3. 判断生成的签名和 jwt 第三部分是否一致
  4. 不一致则返回错误,一致则表示 payload 内的数据可信

总结

jwt 的核心就是密钥,拥有密钥就拥有生成 jwt 的权利(千万不能泄露)。

payload 中的数据不是加密的,不要放敏感数据。

参考资料

  • JSON Web Token - 在Web应用间安全地传递信息
  • 八幅漫画理解使用JSON Web Token设计单点登录系统

你可能感兴趣的:(jwt 就是这么简单)