Angular项目JWT过期检查仅单台机器报atob执行失败错误求助
单台机器上Angular解析JWT时atob解码失败的排查
我在Angular应用中使用以下代码检查JWT令牌的过期时间:
private tokenExpired(token: string) { const expiry = (JSON.parse(atob(decodeURIComponent(token.split('.')[1])))).exp; return (Math.floor((new Date).getTime() / 1000)) >= expiry; }
但遇到了如下错误:
main-es2015.a58e5846e0db8a93ea88.js:1 ERROR Error: Uncaught (in promise): InvalidCharacterError: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded. Error: Failed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded. at A.tokenExpired (main-es2015.a58e5846e0db8a93ea88.js:1) at A.canActivate (main-es2015.a58e5846e0db8a93ea88.js:1) at main-es2015.a58e5846e0db8a93ea88.js:1 at A._subscribe (main-es2015.a58e5846e0db8a93ea88.js:1) at A._trySubscribe (main-es2015.a58e5846e0db8a93ea88.js:1) at A.subscribe (main-es2015.a58e5846e0db8a93ea88.js:1) at PB.call (main-es2015.a58e5846e0db8a93ea88.js:1) at A.subscribe (main-es2015.a58e5846e0db8a93ea88.js:1) at k (main-es2015.a58e5846e0db8a93ea88.js:1) at L._innerSub (main-es2015.a58e5846e0db8a93ea88.js:1) at T (polyfills-es2015.6022d6f28e0500e60d30.js:1) at T (polyfills-es2015.6022d6f28e0500e60d30.js:1) at polyfills-es2015.6022d6f28e0500e60d30.js:1 at l.invokeTask (polyfills-es2015.6022d6f28e0500e60d30.js:1) at Object.onInvokeTask (main-es2015.a58e5846e0db8a93ea88.js:1) at l.invokeTask (polyfills-es2015.6022d6f28e0500e60d30.js:1) at i.runTask (polyfills-es2015.6022d6f28e0500e60d30.js:1) at m (polyfills-es2015.6022d6f28e0500e60d30.js:1)
这个问题只在一台客户端机器上出现,Chrome、Edge、Firefox三款浏览器都受影响。我尝试过替换字符并改用window.atob,代码如下:
private tokenExpired(token: string) { var base64Url = token.split('.')[1]; var base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''); const expiry = (JSON.parse(decodeURIComponent(window.atob(base64)))).exp; return (Math.floor((new Date).getTime() / 1000)) >= expiry; }
但问题依然存在,查阅大量相关帖子也没找到可行方案,恳请分析仅单台机器出现此问题的原因。
可能的原因分析
- 令牌存储损坏:该客户端本地存储(localStorage/sessionStorage)中的JWT令牌可能被意外修改,比如添加了不可见字符、被截断,或者原本的令牌就不符合规范(比如payload部分的base64URL编码长度不是4的倍数,缺少必要的填充符
=) - 浏览器扩展篡改:机器上安装的某些浏览器扩展(比如隐私防护、广告拦截、代理类扩展)可能在令牌传输或存储过程中篡改了内容,导致编码异常
- 系统环境异常:该机器的系统字符编码设置非UTF-8,或者存在系统级的代理/防火墙对HTTP请求中的令牌进行了修改,比如附加了额外字符
- 令牌生成端偶发问题:该用户的令牌可能是服务端某次异常生成的,导致其结构不符合JWT标准,而其他用户的令牌是正常的
验证与修复建议
- 检查该客户端的令牌:让用户导出本地存储的JWT令牌,拆分三段后检查payload部分的编码是否完整,是否有多余字符;也可以用在线JWT解析工具验证令牌是否有效
- 补全base64填充符并增加异常捕获:修改解码逻辑,补全JWT省略的
=填充符,并添加异常捕获,避免崩溃:
private tokenExpired(token: string) { const tokenParts = token.split('.'); if (tokenParts.length !== 3) return true; // 无效令牌直接判定过期 let base64Url = tokenParts[1]; // 补全base64所需的填充字符 base64Url += Array(4 - (base64Url.length % 4)).join('='); // 转换为标准base64格式 const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/').trim(); try { const payload = JSON.parse(window.atob(base64)); const currentTimestamp = Math.floor(Date.now() / 1000); return payload.exp ? currentTimestamp >= payload.exp : true; } catch (error) { console.error('令牌解析失败:', error); return true; // 解析失败时视为令牌过期/无效 } }
- 排查客户端环境:让用户禁用所有浏览器扩展,清除本地存储后重新登录;如果机器使用了代理,暂时关闭代理再测试
- 重置客户端存储:指导用户清除浏览器的本地存储、Cookie,重新获取令牌后验证是否正常
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

