JJWT相关笔记
JWT构成
JWT是由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串 第一部分称为头部(header),第二部分称其为载荷(payload, 类似于飞机上承载的物品),第三部分是签证(signature).
header
jwt的头部承载两部分信息:声明类型,这里是jwt、声明加密的算法(通常直接使用 HMAC SHA256)。对其进行base64加密(可以是对称加密),得到第一部分
payload
载荷就是存放有效信息的地方。这个名字像是特指飞机上承载的货品,这些有效信息包含三个部分:标准中注册的声明、公共的声明、私有的声明。对其进行base64加密,得到第二部分
有效载荷部分,是JWT的主体内容部分,也是一个JSON对象,包含需要传递的数据。 JWT指定七个默认字段供选择(标准中注册的声明)
- iss: jwt签发者
- sub: jwt所面向,使用jwt的用户
- aud: 接收jwt的一方
- exp: jwt的过期时间,这个过期时间必须大于签发时间
- nbf: 定义在指定时间之前,该jwt都是不可用的.
- iat: jwt的签发时间
- jti: jwt的唯一身份标识,主要用来作为一次性token,从而回避重放攻击
除以上默认字段外,还可以自定义私有字段,可以用来存一些必要但非敏感的信息
对于已签名的令牌,此信息尽管可以防止篡改,但任何人都可以读取。除非将其加密,否则请勿将重要信息放入JWT的有效负载或报头元素中(header和payload都是base64编码。盐secret是用于签名的,所以前面两部分没太大的安全性)
载荷部分存在两个属性:payload和claims。两个属性均可作为载荷,jjwt中二者只能设置其一,如果同时设置,在终端方法compact() 中将抛出异常
signature
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:header (base64后的)、payload (base64后的)、secret(盐,不可泄漏)。
base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,就构成了jwt的第三部分。
JWT特点
JWT的特点是无状态的,所以无法解决主动过期及续期的问题(续期实际上是重新颁发token)
JwtBuilder
String jwt = Jwts.builder()
// 这里指定了加密算法和盐secret
.signWith(secret, SignatureAlgorithm.HS512)
// 加入ID确保生成的 Token 都不一致
.setId(IdUtil.simpleUUID())
// 配置私有的声明。解密后可通过jwt.get()获取
.claim(AUTHORITIES_KEY, authentication.getName())
// 这个就是上面的sub。还可以设置些别的。在将jwt解密出claim后,可通过claims.getSubject()获取
.setSubject(authentication.getName())
// 设置颁发时间
.setIssuedAt(curDate)
// 设置过期时间,
// .setExpiration(expirationDate)
.compact();
compact() 生成JWT。过程如下:
- 载荷校验,如果builder中Claims属性为空,则创建DefaultClaims对象,并把键值放入;如果Claims属性不为空,获取之后判断键值,存在则更新,不存在则直接放入。
- 获取key。如果是keyBytes则通过keyBytes及算法名生成key对象。
- 将所使用签名算法写入header。如果使用压缩,将压缩算法写入header。
- 将Json形式的header转为bytes,再Base64编码
- 将Json形式的claims转为bytes,如果需要压缩则压缩,再进行Base64编码
- 拼接header和claims。如果签名key为空,则不进行签名(末尾补分隔符” . “);如果签名key不为空,以拼接的字符串作为参数,按照指定签名算法进行签名计算签名部分 sign(String jwtWithoutSignature),签名部分同样也会进行Base64编码。
- 返回完整JWT
jjwt实现的 DefaultJwtSigner 提供了一个带工厂参数的构造方法。并将jjwt实现的 DefaultSignerFactory静态实例传入,根据不同的签名算法创建对应的签名器进行签名。
有关配置构建器的信息。使用指定的元素和属性来构建令牌。
| Name | Type | Default | Description |
|---|---|---|---|
| audiences | string | 要包含在 JSON Web 令牌的受众声明中的可信受众列表。 | |
| claims | string | 指定要包含在令牌中的声明的逗号分隔列表。具体见上面载荷部分 | |
| contentEncryptionAlgorithm | A256GCM | 指定加密算法,用于将 JWT 纯文本加密以生成 JWE 密文。 A256GCM 将 AES GCM 算法与 256 位的密钥配合使用,以将 JWE 的 JWT 纯文本加密。 | |
| expiresInSeconds | 具有秒精度的时间段 | -1 | 指示令牌到期时间(按秒计)。优先于到期。. 指定后跟时间单位的正整数,时间单位可以是小时 (h)、分钟 (m) 或秒 (s)。例如,以 30s 的形式指定 30 秒。可将多个值包括在单个条目中。例如,1m30s 相当于 90 秒。 |
| expiry | 具有小时精度的时间段 | 2h | 指示令牌到期时间(按小时计)。优先使用 ExpiresInSeconds(如果存在)。. 指定后跟时间单位的正整数,时间单位可以是小时 (h)。例如,以 12h 的形式指定 12 小时。 |
| id | string | defaultJWT | 此标识用来标识 JWT 构建器。如果未指定标识值,那么不会处理构建器。该标识必须是 URL-safe 字符串。如果未指定颁发者配置属性,那么该标识用作颁发者值的一部分。JwtBuilder API 使用此标识来确定要用来构造 JWT 的构建器配置。 |
| issuer | string | 颁发者是使用 HTTP 或 HTTPS 方案的 URL(区分大小写),其中包含方案、主机及(可选的)端口号和路径部分。 | |
| jti | 布尔型 | false | 指示是否生成令牌的唯一标识。 |
| jwkEnabled | 布尔型 | false | 指示是否使用 JWK 对令牌进行签名。 |
| keyAlias | string | 密钥别名,用于查找使用非对称算法对令牌进行签名所需的专用密钥。 | |
| keyManagementKeyAlgorithm | RSA-OAEP | 指定加密算法,用于将 JWE 的内容加密密钥加密。 RSA-OAEP 使用 RSAES OAEP 算法可将 JWE 的内容加密密钥加密。 | |
| keyManagementKeyAlias | string | 这是密钥管理密钥的公用密钥别名,用于将 JWE 的内容加密密钥加密。 | |
| keyStoreRef | 对顶级 keyStore 元素的引用(字符串)。 | 密钥库,包含使用非对称算法对令牌进行签名所必需的专用密钥。 | |
| nbfOffset | 具有秒精度的时间段 | -1 | 标识接受 JWT 以进行处理时的时间。值必须为 NumericDate 对象。. 指定后跟时间单位的正整数,时间单位可以是小时 (h)、分钟 (m) 或秒 (s)。例如,以 30s 的形式指定 30 秒。可将多个值包括在单个条目中。例如,1m30s 相当于 90 秒。 |
| scope | string | 指定 OAuth 作用域的空格分隔列表。 | |
| sharedKey | 可逆向编码的密码(字符串) | 指定将用于生成共享密钥的字符串。可采用明文或更安全的编码格式存储该值。请将 securityUtility 工具与编码选项配合使用以对共享密钥进行编码。 | |
| signatureAlgorithm | ES256ES384ES512HS256HS384HS512RS256RS384RS512 | RS256 | 指定将用于对 JWT 令牌进行签名的签名算法。 ES256 ES384 ES512 HS256 HS384 HS512 RS256 RS384 RS512 |
| trustStoreRef | 对顶级 keyStore 元素的引用(字符串)。 | 密钥库,包含在验证 JWT 令牌的签名时必需的公用密钥。 |
