冷饭新炒:理解JWT的实现原理和基本使用

这是《冷饭新炒》系列的第五篇文章。

冷饭新炒:理解JWT的实现原理和基本使用

本文会翻炒一个用以产生访问令牌的开源标准JWT,介绍JWT的规范、底层实现原理基本使用和应用场景。

JWT规范

很可惜维基百科上没有搜索到JWT的条目,但是从jwt.io的首页展示图中,可以看到描述:

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties

从这段文字中可以提取到JWT的规范文件RFC 7519,里面有详细地介绍JWT的基本概念,Claims的含义、布局和算法实现等,下面逐个展开击破。

JWT基本概念

JWT全称是JSON Web Token,如果从字面上理解感觉是基于JSON格式用于网络传输的令牌。实际上,JWT是一种紧凑的Claims声明格式,旨在用于空间受限的环境进行传输,常见的场景如HTTP授权请求头参数和URI查询参数。JWT会把Claims转换成JSON格式,而这个JSON内容将会应用为JWS结构的有效载荷或者应用为JWE结构的(加密处理后的)原始字符串,通过消息认证码(Message Authentication Code或者简称MAC)和/或者加密操作对Claims进行数字签名或者完整性保护。

这里有三个概念在其他规范文件中,简单提一下:

JWE(规范文件RFC 7516):JSON Web Encryption,表示基于JSON数据结构的加密内容,加密机制对任意八位字节序列进行加密、提供完整性保护和提高破解难度,JWE中的紧凑序列化布局如下

BASE64URL(UTF8(JWE Protected Header)) || '.' || BASE64URL(JWE Encrypted Key) || '.' || BASE64URL(JWE Initialization Vector) || '.' || BASE64URL(JWE Ciphertext) || '.' || BASE64URL(JWE Authentication Tag)

JWS(规范文件RFC 7515):JSON Web Signature,表示使用JSON数据结构和BASE64URL编码表示经过数字签名或消息认证码(MAC)认证的内容,数字签名或者MAC能够提供完整性保护,JWS中的紧凑序列化布局如下:

ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) || '.' || BASE64URL(JWS Signature)

JWA(规范文件RFC 7518):JSON Web Algorithm,JSON Web算法,数字签名或者MAC算法,应用于JWS的可用算法列表如下:

冷饭新炒:理解JWT的实现原理和基本使用

总的来说,JWT其实有两种实现,基于JWE实现的依赖于加解密算法、BASE64URL编码和身份认证等手段提高传输的Claims的被破解难度,而基于JWS的实现使用了BASE64URL编码和数字签名的方式对传输的Claims提供了完整性保护,也就是仅仅保证传输的Claims内容不被篡改,但是会暴露明文。目前主流的JWT框架中大部分都没有实现JWE,所以下文主要通过JWS的实现方式进行深入探讨

JWT中的Claims

Claim有索赔、声称、要求或者权利要求的含义,但是笔者觉得任一个翻译都不怎么合乎语义,这里保留Claim关键字直接作为命名。JWT的核心作用就是保护Claims的完整性(或者数据加密),保证JWT传输的过程中Claims不被篡改(或者不被破解)。Claims在JWT原始内容中是一个JSON格式的字符串,其中单个Claim是K-V结构,作为JsonNode中的一个field-value,这里列出常用的规范中预定义好的Claim:

简称 全称 含义
iss   Issuer   发行方  
sub   Subject   主体  
aud   Audience   (接收)目标方  
exp   Expiration Time   过期时间  
nbf   Not Before   早于该定义的时间的JWT不能被接受处理  
iat   Issued At   JWT发行时的时间戳  
jti   JWT ID   JWT的唯一标识  

这些预定义的Claim并不要求强制使用,何时选用何种Claim完全由使用者决定,而为了使JWT更加紧凑,这些Claim都使用了简短的命名方式去定义。在不和内建的Claim冲突的前提下,使用者可以自定义新的公共Claim,如:

简称 全称 含义
cid   Customer ID   客户ID  
rid   Role ID   角色ID  

一定要注意,在JWS实现中,Claims会作为payload部分进行BASE64编码,明文会直接暴露,敏感信息一般不应该设计为一个自定义Claim。

JWT中的Header

在JWT规范文件中称这些Header为JOSE Header,JOSE的全称为Javascript Object Signature Encryption,也就是Javascript对象签名和加密框架,JOSE Header其实就是Javascript对象签名和加密的头部参数。下面列举一下JWS中常用的Header

简称 全称 含义
alg   Algorithm   用于保护JWS的加解密算法  
jku   JWK Set URL   一组JSON编码的公共密钥的URL,其中一个是用于对JWS进行数字签名的密钥  
jwk   JSON Web Key   用于对JWS进行数字签名的密钥相对应的公共密钥  
kid   Key ID   用于保护JWS进的密钥  
x5u   X.509 URL   X.509相关  
x5c   X.509 Certificate Chain   X.509相关  
x5t   X.509 Certificate SHA-1 Thumbprin   X.509相关  
x5t#S256   X.509 Certificate SHA-256 Thumbprint   X.509相关  
typ   Type   类型,例如JWT、JWS或者JWE等等  
cty   Content Type   内容类型,决定payload部分的MediaType  

最常见的两个Header就是alg和typ,例如:

{ "alg": "HS256", "typ": "JWT" } JWT的布局

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjzjp.html