最近在项目开发中,我遇到了一个令人头疼的问题:JWT解析所依赖的CDN源不稳定。这导致应用在某些情况下无法正常运行,严重影响了用户体验。经过一番探索和尝试,我最终通过手写解析函数的方式解决了这个问题。本文将分享我的解决过程和心得,希望对遇到类似问题的朋友有所帮助。
问题背景
在前端项目中,我使用了 jwt-decode
库来解析JSON Web Token(JWT),并通过CDN方式引入:
<script src="https://cdn.jsdelivr.net/npm/jwt-decode@3.1.2/build/jwt-decode.min.js"></script>
然而,近期发现这个CDN源经常无法访问,导致页面报错,无法获取到用户信息。我尝试更换为另一个常用的CDN:
<script src="https://cdnjs.cloudflare.com/ajax/libs/jwt-decode/3.1.2/jwt-decode.min.js"></script>
结果同样不稳定。这可能是由于网络连接、区域限制或其他原因导致的。
解决方案
尝试本地引入 jwt-decode
库
为了摆脱对CDN的依赖,我首先考虑将 jwt-decode
库下载到本地并在项目中直接引用。然而,当我访问 jwt-decode
的 GitHub 仓库时,发现 build
目录中并没有 jwt-decode.min.js
文件。这使得直接下载库文件的方案行不通。
手写JWT解析函数
经过一番思考,我决定手写一个简单的JWT解析函数,不再依赖外部库。以下是我实现的解析函数:
function parseJwt(token) {var base64Url = token.split('.')[1];var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);}).join(''));return JSON.parse(jsonPayload);
}
详细解析
-
分割JWT字符串
var base64Url = token.split('.')[1];
- JWT由三部分组成,使用点号
.
分隔,格式为:Header.Payload.Signature
。 - 这里通过
split('.')
方法将JWT字符串按点号分割,获取数组中的第二个元素,即中间的 Payload 部分(索引为1)。
- JWT由三部分组成,使用点号
-
转换Base64URL编码为标准Base64编码
var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
- JWT的Payload部分使用的是 Base64URL 编码,它与标准的Base64编码稍有不同:
-
替换为+
_
替换为/
- 通过
replace
方法,将Base64URL编码转换回标准的Base64编码,便于后续解码。
- JWT的Payload部分使用的是 Base64URL 编码,它与标准的Base64编码稍有不同:
-
解码Base64编码的字符串
var jsonPayload = decodeURIComponent(atob(base64).split('').map(function (c) {return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2);}).join('') );
atob(base64)
:使用atob
函数将Base64编码的字符串解码为原始的二进制数据(这里是UTF-8编码的字符串)。- 处理特殊字符:
split('')
:将字符串拆分为单个字符的数组。map(function (c) { /* ... */ })
:遍历每个字符,执行以下操作:c.charCodeAt(0).toString(16)
:获取字符的Unicode编码,并转换为十六进制字符串。('00' + /* ... */).slice(-2)
:确保每个十六进制编码占两位,不足两位的前面补零。'%' + /* ... */
:在每个编码前加上%
,形成百分比编码(URI编码)的形式。
join('')
:将数组重新拼接成字符串。
decodeURIComponent(/* ... */)
:将百分比编码的字符串解码为正常的UTF-8字符串,即还原成JSON格式的字符串。
-
解析JSON字符串
return JSON.parse(jsonPayload);
- 使用
JSON.parse
方法,将JSON格式的字符串解析为JavaScript对象,便于后续访问其中的数据。
- 使用
补充说明
- Base64URL编码:是一种URL安全的Base64编码方式,避免了在URL中出现
+
和/
等特殊字符。 atob
函数:用于解码Base64编码的字符串。在某些旧版本的浏览器中可能不支持,需注意兼容性。decodeURIComponent
函数:用于解码URI编码的字符串,将百分比编码转换为正常字符。
效果:
- 成功解析JWT,获取到信息。
- 不再依赖任何外部库,提升了应用的稳定性。
注意事项
- 安全性考虑:该函数只解析JWT的Payload部分,不会验证签名的有效性。如果应用对安全性要求较高,建议使用经过验证的库来解析和验证JWT的签名。
- 兼容性:手写的解析函数适用于标准的JWT格式,如果JWT的编码方式有变动,可能需要相应调整解析逻辑。
总结
通过手写解析函数,我成功解决了JWT解析CDN不稳定的问题,提升了应用的稳定性和可靠性。这次经历让我认识到,过度依赖外部资源可能带来的风险。在今后的开发中,我会更加注意:
- 减少对外部依赖的依赖:关键功能尽量本地化,必要时自行实现。
- 提升应用的健壮性:提前考虑可能的异常情况,提供备用方案。
- 关注安全性:在自行实现功能时,务必考虑到安全因素,确保应用的安全性不受影响。
希望我的经验对大家有所帮助,也欢迎交流其他更好的解决方案。