什么是 JWT?
JSON Web Token(JWT)是一种开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,作为JSON对象在各方之间安全的传递信息。这个信息可以通过数字签名进行验证并信任。JWTs 可以使用密钥(结合HMAC算法)或者 使用RSA、ECDSA加密的公钥私钥对进行签名。
尽管JWTs能够在各方之间也提供安全加密,但是仍专注于签名Token。当其他方隐藏了加密Token的某些声明时,签名Token可以验证声明的完整性。当Token使用公钥私钥对进行签名时,这个签名还能证明只有拥有私钥的一方才是签发它的一方。
什么时候使用 JWT ?
- 授权:这是JWT最普遍的使用场景了。当用户登录之后,每次请求都包含JWT,允许用户访问那些只有携带token才能访问的路由、服务、资源。如今在单点登录中广泛使用了JWT,因为JWT体积小,且能够在不同域名之间被使用。
- 信息交换:JWT是一种在各方之间安全传输信息的好方式。因为JWTs能够签名,比如使用公钥私钥对,你能够确定发送者的身份。另外,签名是使用header和payload计算而来,所以你也可以验证内容是否被篡改。
JWT的结构
jwt 包含三部分,之间以点(.)分隔
- Header(头部)
- Payload(负载)
- Signature(签名)
一个典型的jwt如同下面这样:
xxxxx.yyyyy.zzzzz
下面分别介绍他们
Header
Header部分 是一个 JSON 对象,典型的header包含两部分:
alg
:使用的签名算法,比如 HMAC SHA256 或 RSAtyp
:token的类型,比如 JWT
{
"alg": "HS256",
"typ": "JWT"
}
最后,用 Base64Url 将这个 JSON 对象编码后,作为 JWT 的第一部分
Payload
Payload 部分也是 JSON 对象,用来存放数据。JWT 有7个官方字段
* iss (issuer):签发人
* exp (expiration time):过期时间,以秒为单位
* iat (Issued At):签发时间,能够算出JWT的存在时间
* nbf (Not Before):生效时间
* jti (JWT ID):JWT 的唯一标识。用来防止 JWT 重复。
* sub (subject):主题(很少使用)
* aud (audience):token的受众(很少被使用)
除了上面这些字段,还可以自定义私有字段,比如
{
"userId": "1101",
"userName": "张三",
"age": "23"
}
最后,用 Base64Url 将这个 JSON 对象编码后,作为 JWT 的第二部分
Tip: JWT 默认不加密,任何人都可以读取,所以不要把敏感信息存放在这个部分,除非加密过。
Signature
使用 Header 指定的算法对 Header、Payload、密钥三部分进行签名生成的字符串,作为签名部分。
比如使用 HMAC SHA256 算法
HMACSHA256(
Base64Url.encode(header) + "." + Base64Url.encode(payload),
secret
)
签名被用来验证数据是否被篡改,并且如果 token 使用了私钥进行签名,那么签名还可以验证 JWT 的发送者身份。
怎么使用 JWT ?
客户端收到服务器返回的 JWT,可以储存在 Cookie 里面,也可以储存在 localStorage。
此后,客户端每次请求服务器,都要带上这个 JWT。可以把它放在 Cookie 里面自动发送,但是这样并不能跨域,所以更好的做法是放在 HTTP 请求的头信息 Authorization
字段里面。
Authorization: Bearer <token>
另一种做法是,跨域的时候,JWT 就放在 POST 请求的数据体里面。
JWT 的特点
- JWT 默认是不加密,但也是可以加密的。生成原始 Token 以后,可以用密钥再加密一次。
JWT 不加密的情况下,不能将秘密数据写入 JWT。
- JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
- JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
- JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用 HTTPS 协议传输。
和 Session-Cookie 相比
Session-Cookie 方式:客户端每次请求都使用 cookie 携带 session_id ,服务器根据 session_id 区分不同的会话
JWT 方式:客户端每次请求都使用请求头携带 token,服务器根据 token 区分不同的用户