jwt简析

什么是JWT

官方文档定义

JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以将各方之间的信息作JSON对象进行安全传输。该信息可以通过数字签名验证和信任。使用secret(使用HMAC算法)或使用RSA的公钥/私钥对可以对JWT进行签名。

进一步解释

  • 紧凑

    因为jwt有很小,所以能很容易的用在URL,POST参数,HTTP头中,另外也是因为小,所以传输起来很快。

  • 独立

    jwt的payload部分包含所有用户需要的信息,避免多次去db查询。

那什么时候用JWT

认证(Authentication)

这是应用JWT最常用的一个场景,一旦用户登录,那么其后来的请求就要包含用来访问路由,服务,资源等的token,SSO(Single Sign On)是当下广泛应用JWT的应用,因为它成本小并且很容易解决跨域问题。

信息交互

JWT是一种很好的安全的信息传递方式,因为JWT是被签名过的,举个例子,可以用公私钥对,信息的发送是安全可信任的。另外,因为签名能通过header和payload部分计算出来,你可以验证内容有没有被篡改过。

JWT的结构组成

JWT有.分割的三部分构成,分别是

  • Header(头)
  • Payload(载荷)
  • Signature(签名)

所以一个完整JWT看起来像是这样:

xxxx.yyyy.zzzz

我们拆开分别介绍这三部分

典型的Header包含两部分:token类型(也就是jwt) 和 hash算法(HMAC SHA256 RSA)

比如

1
2
3
4
{
"alg": "HS256",
"typ": "JWT"
}

然后通过Base64Url encoded,生成JWT的第一部分。

Payload

JWT的第二部分包含claimsClaims 存储着一个实体的状态还有其他附加信息等,有三种类型的claims

reserved

预定义好的claims的一个集合,不强制,但是建议使用,iss (issuer), exp (expiration time), sub(subject), aud (audience)

  • iss: jwt签发者
  • sub: jwt所面向的用户
  • aud: 接收jwt的一方
  • exp: jwt的过期时间,这个过期时间必须要大于签发时间
  • nbf: 定义在什么时间之前,该jwt都是不可用的.
  • iat: jwt的签发时间
  • jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击。

Notice that the claim names are only three characters long as JWT is meant to be compact.

注意:这个claim的名字只有三个字符长度,也符合JWT是紧凑的目标。

public

公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息.但不建议添加敏感信息,因为该部分在客户端可解密.

priavate

私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为base64是对称解密的,意味着该部分信息可以归类为明文信息。

例子

1
2
3
4
5
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}

同样用Base64Url encoded之后生成JWT第二部分

Signature

要生成签名,需要用到前面加密后的Header和加密后的Payload,还有一个secret,用在Header的加密算法进行加密。

举个例子,用HMAC SHA256算法

1
2
3
4
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)

签名是用来验证发送过来的JWT是否像他们说的那样可信,保证信息没有被修改。

三部分放在一起

注意:secret是保存在服务器端的,jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了。

如何应用

一般是在请求头里加入Authorization,并加上Bearer标注:

1
Authorization: Bearer <token>

服务端会验证token,如果验证通过就会返回相应的资源。整个流程就是这样的

安全相关

  • 不应该在jwt的payload部分存放敏感信息,因为该部分是客户端可解密的部分。
  • 保护好secret私钥,该私钥非常重要。
  • 如果可以,请使用https协议
坚持技术分享,您的支持将鼓励我继续创作!