首页 > 解决方案 > JWT 标头缺少“类型”字段

问题描述

我正在使用以下代码创建 JWT:

long now = Instant.now().getEpochSecond();
long exp = now + TimeUnit.HOURS.toSeconds(1);
long nbf = now - TimeUnit.MINUTES.toSeconds(5);

String jwt = Jwts.builder()
                .setSubject("d45049c3-3441-40ef-ab4d-b9cd86a17225")
                .claim("iss", "d45049c3-3441-40ef-ab4d-b9cd86a17225")
                .claim("aud", "https://apporchard.epic.com/interconnect-aocurprd-oauth/oauth2/token")
                .claim("jti", UUID.randomUUID().toString())
                .claim("exp", exp)
                .claim("nbf", nbf)
                .claim("iat", now)
                .signWith(key, SignatureAlgorithm.RS384)
                .compact();

但是当我查看创建的 JWT 的 JSON 版本时,标头是

{
  "alg": "RS384"
}

它缺少“典型”字段。我认为这个字段是强制性的。

标签: jjwt

解决方案


根据RFC 7519,第 5.1 节typ,标题是可选的(粗体强调是我的):

当不是 JWT 的值也可能出现在可以包含 JWT 对象的应用程序数据结构中时,这是供 JWT 应用程序使用的 ;应用程序可以使用该值来区分可能存在的不同类型的对象。当已知对象是 JWT 时,应用程序通常不会使用它。 JWT 实现忽略此参数;此参数的任何处理都由 JWT 应用程序执行。

因此,根据最后的粗体行,JJWT(作为 JWT 实现)不会设置或读取它,因为实现会忽略它。

如果您愿意,您(如JWT application上述白话)可以自己设置值:

Jwts.builder().setHeaderParam("typ", yourMediaTypeValue)
    ...

但同样,正如规范所说,如果您已经知道您正在使用 jwt 的字符串,则不需要这样做。如果 JWT 嵌入到其他内容中并且您需要区分 jwt 和其他内容之间的区别,您只需要真正设置该值。

它通常用于非紧凑(完整 JSON)JWT 文档,而不是紧凑 JWS 或 JWE 值,其中完整 JSON 对象需要与其他(非紧凑)JSON 值消除歧义。


推荐阅读