生成 JWT 令牌

Posted

技术标签:

【中文标题】生成 JWT 令牌【英文标题】:Generating JWT tokens 【发布时间】:2021-07-29 14:14:57 【问题描述】:

谁能为我提供一个生成 jwt 令牌的示例,该令牌具有三个标头(alg、kid、typ),其格式如下:


  "alg": "RS256",
  "kid": "vpaas-magic-cookie-1fc542a3e4414a44b2611668195e2bfe/4f4910",
  "typ": "JWT"

在https://developer.8x8.com/jaas/docs/api-keys-jwt下。

Jwt 令牌在几个小时的时间限制内过期,因此我正在尝试找到一种方法在我的代码本身中生成令牌。

最后,我的 javascript 看起来像这样,我在选项列表中添加 jwt 令牌以进行身份​​验证。

var options = 
                roomName: "vpaas-magic-cookie-secretKey/Room123",
                jwt: 'JWTTOKEN',
                ,

根据我在https://jwt.io/ 下阅读的内容,我需要来自解码细节的编码密钥。根据生成令牌,我认为它使用 HS256 算法。在 javascript 中执行此操作的步骤是什么?

编辑:在用户回答后,我对他的代码进行了一些更改,目前正在生成一半的 JWT 令牌。我正在使用服务器上已经生成的令牌检查它 - Jaas.8x8

<script>
    const HMACSHA256 = (stringToSign, secret) => "not_implemented"

    // The header typically consists of two parts: 
    // the type of the token, which is JWT, and the signing algorithm being used, 
    // such as HMAC SHA256 or RSA.
    const header = 
        "kid": "vpaas-magic-cookie-07fabede3674457a84c95fsecretcode/myroom001",
        "alg": "RS256",
        "typ": "JWT"
    
    const encodedHeaders = btoa(JSON.stringify(header))


    // create the signature part you have to take the encoded header, 
    // the encoded payload, a secret, the algorithm specified in the header, 
    // and sign that.
    const signature = HMACSHA256(`$encodedHeaders`, "mysecret")


    console.log(`$encodedHeaders.$signature`)
</script>

从代码生成的令牌是

eyJraWQiOiJ2cGFhcy1tYWdpYy1jb29raWUtMDdmYWJlZGUzNjc0NDU3YTg0Yzk1ZmE4MGIxNGY1ZDcvVGVzdFJhdW0wMDEiLCJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.not_implemented

而网上已经生成的token是:

eyJraWQiOiJ2cGFhcy1tYWdpYy1jb29raWUtMDdmYWJlZGUzNjc0NDU3YTg0Yzk1ZmE4MGIxNGY1ZDcvMTg1ZDY2LVNBTVBMRV9BUFAiLCJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJqaXRzaSIsImV4cCI6MTYyMDM4ODU3NiwibmJmIjoxNjIwMzgxMzcxLCJpc3MiOiJjaGF0Iiwicm9vbSI6IioiLCJzdWIiOiJ2cGFhcy1tYWdpYy1jb29raWUtMDdmYWJlZGUzNjc0NDU3YTg0Yzk1ZmE4MGIxNGY1ZDciLCJjb250ZXh0Ijp7ImZlYXR1cmVzIjp7ImxpdmVzdHJlYW1pbmciOmZhbHNlLCJvdXRib3VuZC1jYWxsIjpmYWxzZSwidHJhbnNjcmlwdGlvbiI6ZmFsc2UsInJlY29yZGluZyI6ZmFsc2V9LCJ1c2VyIjp7Im1vZGVyYXRvciI6dHJ1ZSwibmFtZSI6IlRlc3QgVXNlciIsImlkIjoiYXV0aDB8NjA5M2EyYzM3Zjc3MGEwMDcxMGE5YzY5IiwiYXZhdGFyIjoiIiwiZW1haWwiOiJ0ZXN0LnVzZXJAY29tcGFueS5jb20ifX19.aNqg_VLXyafH8Se5rThe6TLz0F2AEnJSmuoZBQ4fXEm1PMx4SBRpelJsrmL76D_jKS5NT-GkuPDVcDgLv6nx9G4ywjws1AH4Lkt0FcJ3eH2OjbFI2WxPzJF_tDJbtPme5LJmGZwEa509v2QD0r-kr31M7FZ83S-kz3O1xKc33FnMJwNlqvgCSN2S0QwF6R5J01zDk41gCk0wGr3DXAmlz0FtCU0qJ5nN9iMUpr5QUY1D-hRApWMhoLPmxkuqnQKLjGwgxU8lh33wq_Laqu7qV57lYrI27er_c42YePwuitWEAAshQU4Ylf2v8sVRv06kQdFPVvICVdsTTI-DLbc3aQ

所以基本上前几个字符串是正确的,但其余的没有生成。我认为这与我的秘密有关?这究竟是什么?

【问题讨论】:

"Jwt 令牌在几个小时的时间限制内过期,所以我正在尝试找到一种方法在我的代码中生成令牌。"如果你只需要一个更长寿的令牌,你可以考虑调整令牌的过期时间,而不是在这里重新发明***。 @HenryEcker 感谢您的回复。我想这样做,但我获取 JWT 令牌的 api-keys 的最大限制只有 2 小时。 你是想用普通的 javascript 来做,还是想要一个令牌? @TheFool 我正在尝试用普通的 js 来做,我在 javascript 中遇到了 base64 标头。也许这就是做到这一点的关键? 您在问题开头发布的标头来自使用非对称算法签名的令牌。要创建此类令牌,​​您需要有权访问授权服务器的私有证书,该证书用于签署令牌。您尝试做的事情似乎不正确 - 您不能在代码中发布令牌并期望它们像某些不同的授权服务器发布的令牌一样工作。除非您拥有服务器的私钥,否则您只能模仿这种行为。 【参考方案1】:

所有的说明都写在这个页面上,https://jwt.io/introduction。

为简单起见,我没有实现 HMACSHA256 或使用库来实现。你需要实现这个功能。

如果你想从没有多大意义的浏览器中进行操作,How to get HMAC with Crypto Web API。 如果你想从节点(后端)做,这更有意义,你可以看看这个https://www.nodejsera.com/snippets/nodejs/sha256-hmac.html

我还认为根据规范,您的标题无效。这个孩子属性可能应该进入有效载荷。

const HMACSHA256 = (stringToSign, secret) => "not_implemented"

// The header typically consists of two parts: 
// the type of the token, which is JWT, and the signing algorithm being used, 
// such as HMAC SHA256 or RSA.
const header = 
  "alg": "HS256",
  "typ": "JWT",
  "kid": "vpaas-magic-cookie-1fc542a3e4414a44b2611668195e2bfe/4f4910"

const encodedHeaders = btoa(JSON.stringify(header))


// The second part of the token is the payload, which contains the claims.
// Claims are statements about an entity (typically, the user) and 
// additional data. There are three types of claims: 
// registered, public, and private claims.
const claims = 
    "role": "admin"

const encodedPlayload = btoa(JSON.stringify(claims))


// create the signature part you have to take the encoded header, 
// the encoded payload, a secret, the algorithm specified in the header, 
// and sign that.
const signature = HMACSHA256(`$encodedHeaders.$encodedPlayload`, "mysecret")
const encodedSignature = btoa(signature)

const jwt = `$encodedHeaders.$encodedPlayload.$encodedSignature`
console.log(jwt)

【讨论】:

非常感谢您的解释。我对您的代码进行了一些更改,因为它现在正在生成前几个字符串。但不完全。这里的“mysecret”到底是什么,我需要添加什么“not_implemented”?因为这些信息不是从服务器提供的。另外,你能看看编辑过的问题吗? mysecret 是您用来加密签名的密钥。服务器拥有此密钥,它将使用它来解密签名并验证令牌。您需要提供与服务器知道的完全相同的秘密字符串。 未实现意味着你需要自己编写这个函数。看看我发布的 2 个链接。他们展示了如何制作 hmac sha256 字符串 kid 如果令牌是用非对称算法签名的(最初我们可以看到它是用 RS256 签名的),则属于令牌头。在您的示例中,您应该使用alg: "HS256",这是使用 HMACSHA256 签名的令牌的正确值。 您在这里使用btoa,它对字符串进行base64编码,但实际上对于JWT,您必须使用base64url编码。 (未实现的)HMAC 签名也需要进行 base64url 编码。

以上是关于生成 JWT 令牌的主要内容,如果未能解决你的问题,请参考以下文章

生成 JWT 令牌

使用slim-jwt-auth生成令牌

生成 AR-JWT 令牌 [关闭]

生成令牌 JWT

使用 slim-jwt-auth 生成令牌

如何使用 JWT 刷新令牌生成新的访问令牌