使用base64 -d无法完整解码JWT负载的原因及解决方法
JWT负载Base64解码终端与浏览器结果不一致问题
问题背景
JWT由header.payload.signature三部分组成,以下是待解码的JWT负载:
payload=eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTY3OTMxMzgyMSwiaWF0IjoxNjc5MTQxMDIxLCJqdGkiOiIzZjM4ZTVmZTBmNGE0N2E0ODg2MGM4M2FmYmNhNTAzZiIsInVzZXJfaWQiOjEwfQ
在OS X终端执行echo $payload | base64 -d后,输出被截断:
{"token_type":"refresh","exp":1679313821,"iat":1679141021,"jti":"3f38e5fe0f4a47a48860c83afbca503%
但在Chrome浏览器控制台用atob(payload)解码,能得到完整正确的JSON:
{"token_type":"refresh","exp":1679313821,"iat":1679141021,"jti":"3f38e5fe0f4a47a48860c83afbca503f","user_id":10}
疑问
- 为何两者输出不同?据我所知它们都是Base64解码工具。
- 如何在终端使用
base64 -d或类似命令正确解码该负载?
补充信息:
which base64返回/usr/bin/base64- 操作系统:OS X
解答
1. 输出不同的原因
JWT使用的是Base64URL编码,而非标准Base64编码,两者存在核心差异:
- Base64URL会将标准Base64中的
+替换为-、/替换为_,并且省略末尾的填充符= - OS X自带的
base64工具是标准Base64解码器,处理非标准的Base64URL内容时,若内容长度不是4的倍数(缺少填充符),解码流程会异常,导致输出截断或乱码 - Chrome的
atob()方法对Base64URL做了兼容性处理,会自动补全缺失的填充符并替换特殊字符,因此能正确解码
2. 终端正确解码的方法
有两种可行方案:
方案一:手动转换Base64URL为标准Base64后解码
先替换特殊字符,再补全填充符,最后用base64 -d解码:
echo "$payload" | tr '_-' '/+' | awk '{while(length($0)%4) $0=$0"="; print}' | base64 -d
tr '_-' '/+':将Base64URL的_和-转换为标准Base64的/和+awk命令:自动补全末尾的=,确保内容长度是4的倍数
方案二:使用openssl工具直接解码
openssl的base64命令原生支持Base64URL,添加-url参数即可:
echo "$payload" | openssl base64 -d -url
内容的提问来源于stack exchange,提问作者Tobias Braun
相关产品推荐
相关产品推荐

