生成 JWT 的正确方法

Posted

技术标签:

【中文标题】生成 JWT 的正确方法【英文标题】:Correct way to generate JWTs 【发布时间】:2021-05-30 06:55:08 【问题描述】:

我是 JWT 的新手,所以我使用了一篇文章告诉我生成这样的 JWT:

// Create token header as a JSON string
    $header = json_encode(['typ' => 'JWT', 'alg' => 'HS256']);
    
    // Create token payload as a JSON string
    $payload = json_encode(['userId' => $userId, 'exp' => time()+60*60*24*30]);

    // Encode Header to Base64Url String
    $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));

    // Encode Payload to Base64Url String
    $base64UrlPayload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($payload));
 
    // Create Signature Hash
    $signature = hash_hmac('sha256', $base64UrlHeader . "." . $base64UrlPayload, 'mySecret', true);

    // Encode Signature to Base64Url String
    $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));

    // Create JWT
    $jwt = $base64UrlHeader . "." . $base64UrlPayload . "." . $base64UrlSignature;

我想知道 str_replace 是否有必要,因为我认为它会干扰 JWT 的验证?

谢谢。

【问题讨论】:

【参考方案1】:

这是正确且必要的,除非你可以直接base64url编码,因为它把编码从base64变成了base64url,也就是encoding format that JWT uses。

Base64 和 Base64Url 编码几乎相同,只有 2 个字符,'+' 和 '/' 需要替换为 '-' 和 '_' 以及从字符串中删除的填充。 str_replace 正是这样做的。

签名的内容不受此影响,与验证相关的只是解码后的值。

关于“正确方式”的一般问题:从技术上讲,您的方式是正确的,并且有利于教育目的。很高兴知道事情是如何运作的。对于任何现实生活中的应用程序,都有很多 libraries 可以为您完成这项工作。

【讨论】:

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

JWT 令牌认证 - 以正确的方式做事

如何为 spring oauth2 jwt 服务器生成正确的 jwks 端点?

登陆权限--token 的生成和验证

登陆权限--token 的生成和验证

使用 jsonwebtoken 库生成的 JWT 令牌在 jwt.io 中提供了无效签名

在 javascript 中为 JWT 生成 JTI 声明