Skip to main content

7. Creating and Validating JWTs (创建和验证JWT)

7.1. Creating a JWT (创建JWT)

要创建JWT,执行以下步骤。在步骤的输入和输出之间没有依赖关系的情况下,步骤的顺序不重要。

  1. 创建包含所需声明的JWT声明集。请注意,表示中明确允许空格,并且在编码之前无需执行规范化。

  2. 让消息 (Message) 为JWT声明集的UTF-8表示的字节。

  3. 创建包含所需头部参数集的JOSE Header。JWT必须 (MUST) 符合 [JWS] 或 [JWE] 规范。请注意,表示中明确允许空格,并且在编码之前无需执行规范化。

  4. 根据JWT是JWS还是JWE,有两种情况:

    • 如果JWT是JWS,使用消息作为JWS有效载荷创建JWS; 必须 (MUST) 遵循 [JWS] 中指定的创建JWS的所有步骤。

    • 否则,如果JWT是JWE,使用消息作为JWE的明文创建JWE; 必须 (MUST) 遵循 [JWE] 中指定的创建JWE的所有步骤。

  5. 如果将执行嵌套签名或加密操作,让消息为JWS或JWE,并返回到步骤3,在该步骤中创建的新JOSE Header中使用"cty" (content type) 值"JWT"。

  6. 否则,让生成的JWT为JWS或JWE。

7.2. Validating a JWT (验证JWT)

验证JWT时,执行以下步骤。在步骤的输入和输出之间没有依赖关系的情况下,步骤的顺序不重要。如果列出的任何步骤失败,则必须 (MUST) 拒绝JWT——即,应用将其视为无效输入。

  1. 验证JWT至少包含一个句点('.')字符。

  2. 让编码的JOSE Header为第一个句点('.')字符之前的JWT部分。

  3. 按照未使用换行符、空格或其他附加字符的限制对编码的JOSE Header进行Base64url解码。

  4. 验证生成的字节序列是完全符合RFC 7159 [RFC7159] 的UTF-8编码的JSON对象表示; 让JOSE Header为此JSON对象。

  5. 验证生成的JOSE Header不包含重复的头部参数名称。当使用的JSON解析器仅返回词法上最后一个重复成员名称时(如ECMAScript 5.1 [ECMAScript] 第15.12节中指定的),可以自动实现此步骤。

  6. 确定JWT是JWS还是JWE,方法是检查JOSE Header的"enc" (encryption algorithm) 头部参数是否存在。

    • 如果存在"enc"头部参数,则JWT是JWE。

    • 否则,JWT是JWS。

  7. 根据JWT是JWS还是JWE,有两种情况:

    • 如果JWT是JWS,遵循 [JWS] 中指定的使用JOSE Header中的算法和密钥以及JWS有效载荷和JWS签名验证JWS的步骤。让消息为JWS有效载荷。

    • 否则,如果JWT是JWE,遵循 [JWE] 中指定的使用JOSE Header中的算法和密钥解密JWE的步骤。让消息为解密结果的明文。

  8. 如果JOSE Header包含值为"JWT"的"cty" (content type) 头部参数,则JWT是嵌套JWT (Nested JWT)。在这种情况下,返回到步骤1,使用消息作为JWT。

  9. 否则,按照未使用换行符、空格或其他附加字符的限制对消息进行Base64url解码。

  10. 验证生成的字节序列是完全符合RFC 7159 [RFC7159] 的UTF-8编码的JSON对象表示; 让JWT声明集为此JSON对象。

  11. 验证JWT声明集不包含重复的声明名称。当使用的JSON解析器仅返回词法上最后一个重复成员名称时(如ECMAScript 5.1 [ECMAScript] 第15.12节中指定的),可以自动实现此步骤。

最后,请注意,当应用使用多个密钥时,它可能会尝试使用不同的密钥多次验证JWS或JWE。如果应用确定使用特定密钥失败,可能会继续尝试其他密钥,直到成功或用尽所有密钥。

7.3. String Comparison Rules (字符串比较规则)

JWT的处理需要比较JSON字符串值。

声明名称和头部参数名称的比较始终作为区分大小写的字符串执行,不进行类型转换。

StringOrURI值中的URI和JSON字符串值的比较按如下方式执行:

  • 如果一个值是URI而另一个值不是URI,则两个值不同。

  • 如果两个值都是URI,则它们使用区分大小写的字符串比较进行比较,不进行类型转换、规范化或处理反斜杠转义。

  • 如果两个值都不是URI,则它们使用区分大小写的字符串比较进行比较,不进行类型转换或处理反斜杠转义。

请注意,对于任何给定用例,可能应该对URI和其他字符串应用更宽松或更严格的比较规则,但这些比较规则必须 (MUST) 明确指定。