7. Creating and Validating JWTs (创建和验证JWT)
7.1. Creating a JWT (创建JWT)
要创建JWT,执行以下步骤。在步骤的输入和输出之间没有依赖关系的情况下,步骤的顺序不重要。
-
创建包含所需声明的JWT声明集。请注意,表示中明确允许空格,并且在编码之前无需执行规范化。
-
让消息 (Message) 为JWT声明集的UTF-8表示的字节。
-
创建包含所需头部参数集的JOSE Header。JWT必须 (MUST) 符合 [JWS] 或 [JWE] 规范。请注意,表示中明确允许空格,并且在编码之前无需执行规范化。
-
根据JWT是JWS还是JWE,有两种情况:
-
如果JWT是JWS,使用消息作为JWS有效载荷创建JWS; 必须 (MUST) 遵循 [JWS] 中指定的创建JWS的所有步骤。
-
否则,如果JWT是JWE,使用消息作为JWE的明文创建JWE; 必须 (MUST) 遵循 [JWE] 中指定的创建JWE的所有步骤。
-
-
如果将执行嵌套签名或加密操作,让消息为JWS或JWE,并返回到步骤3,在该步骤中创建的新JOSE Header中使用"cty" (content type) 值"JWT"。
-
否则,让生成的JWT为JWS或JWE。
7.2. Validating a JWT (验证JWT)
验证JWT时,执行以下步骤。在步骤的输入和输出之间没有依赖关系的情况下,步骤的顺序不重要。如果列出的任何步骤失败,则必须 (MUST) 拒绝JWT——即,应用将其视为无效输入。
-
验证JWT至少包含一个句点('.')字符。
-
让编码的JOSE Header为第一个句点('.')字符之前的JWT部分。
-
按照未使用换行符、空格或其他附加字符的限制对编码的JOSE Header进行Base64url解码。
-
验证生成的字节序列是完全符合RFC 7159 [RFC7159] 的UTF-8编码的JSON对象表示; 让JOSE Header为此JSON对象。
-
验证生成的JOSE Header不包含重复的头部参数名称。当使用的JSON解析器仅返回词法上最后一个重复成员名称时(如ECMAScript 5.1 [ECMAScript] 第15.12节中指定的),可以自动实现此步骤。
-
确定JWT是JWS还是JWE,方法是检查JOSE Header的"enc" (encryption algorithm) 头部参数是否存在。
-
如果存在"enc"头部参数,则JWT是JWE。
-
否则,JWT是JWS。
-
-
根据JWT是JWS还是JWE,有两种情况:
-
如果JWT是JWS,遵循 [JWS] 中指定的使用JOSE Header中的算法和密钥以及JWS有效载荷和JWS签名验证JWS的步骤。让消息为JWS有效载荷。
-
否则,如果JWT是JWE,遵循 [JWE] 中指定的使用JOSE Header中的算法和密钥解密JWE的步骤。让消息为解密结果的明文。
-
-
如果JOSE Header包含值为"JWT"的"cty" (content type) 头部参数,则JWT是嵌套JWT (Nested JWT)。在这种情况下,返回到步骤1,使用消息作为JWT。
-
否则,按照未使用换行符、空格或其他附加字符的限制对消息进行Base64url解码。
-
验证生成的字节序列是完全符合RFC 7159 [RFC7159] 的UTF-8编码的JSON对象表示; 让JWT声明集为此JSON对象。
-
验证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) 明确指定。