如何通过Bash脚本正确生成JWT的HMACSHA256签名?
问题:Bash脚本生成的JWT签名验证失败
我正在尝试通过终端/Bash脚本创建JWT令牌,当前使用的代码如下:
header='{"typ": "JWT", "alg": "HS256"}' payload= '{"iss": "'"dummy_key"'"}' encoded_header=$(printf "$header" | openssl base64 -e -A | tr -d '=') encoded_payload=$(printf "$payload" | openssl base64 -e -A | tr -d '=') data=$encoded_header.$encoded_payload signature=$(printf '%s' "$data" | openssl dgst -sha256 -hmac dummy_secret -binary | openssl base64 -e -A | tr -d '=')
变量data能输出由点(.)连接的有效header和payload(这些值已提前存储在脚本变量中,header与payload均无问题)。
当我将完整JWT令牌(即$data.$signature)的输出示例:
eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJIUzI1NiJ9Cg.eyJleHAiOiAxNzI0MDczMzI1LCAiaXNzIjogImR1bW15X2tleSJ9Cg./LI0Qs6U1p8x1zRFCwUe2kHW224L9js3fVW3UjpxO70
粘贴到JWT验证工具时,收到“Invalid Signature”错误,提示内容如下:
Warning: Looks like your JWT signature is not encoded correctly using base64url. Note that the padding ("=" must be omitted as per RFC4648规范
我查阅过OpenSSL文档,原以为操作正确,但该错误让我产生疑问。请问如何编写Bash脚本命令,才能为上述JWT的header和payload生成有效的签名?
解决办法
JWT要求使用Base64URL编码,而非普通Base64编码,两者核心差异是:
- 将普通Base64中的
+替换为- - 将
/替换为_ - 移除所有填充字符
=
你的脚本仅完成了移除=的操作,缺少字符替换步骤,同时需避免输出多余换行。修改后的完整脚本如下:
header='{"typ": "JWT", "alg": "HS256"}' payload='{"iss": "dummy_key"}' # 对header做Base64URL编码 encoded_header=$(printf '%s' "$header" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # 对payload做Base64URL编码 encoded_payload=$(printf '%s' "$payload" | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') data="$encoded_header.$encoded_payload" # 生成签名并做Base64URL编码 signature=$(printf '%s' "$data" | openssl dgst -sha256 -hmac "dummy_secret" -binary | openssl base64 -e -A | tr '+/' '-_' | tr -d '=') # 输出完整JWT echo "$data.$signature"
关键修改点说明:
- Base64转Base64URL:在移除
=前增加tr '+/' '-_',替换特殊字符以符合URL安全要求 - 避免多余换行:使用
printf '%s' "$variable"代替printf "$variable",防止默认添加换行或解析字符串中的格式符 - 变量赋值修正:原代码中
payload= '{"iss": "'"dummy_key"'"}'的赋值存在多余空格,修正为payload='{"iss": "dummy_key"}'(也可保留原拼接写法,但需去掉空格)
修改后生成的JWT签名即可通过验证工具的检查。
内容的提问来源于stack exchange,提问作者N. Blore
相关产品推荐
相关产品推荐

