JavaScript中如何保护Token等变量不被第三方脚本非法访问?
现有方案可行性评估
- 方案1(全应用嵌入沙箱iframe):可行性较低。多层iframe嵌套会带来显著的性能损耗、通信链路复杂度提升,同时沙箱限制会导致大量原有业务逻辑需要适配改造,投入产出比很低,不推荐作为核心方案。
- 方案2(权限受限专用Token):可行性很高,属于最小权限原则的标准落地。你可以为第三方脚本运行域单独签发短有效期、仅覆盖脚本必要操作权限的专用Token,和主应用高权限Token完全隔离,就算被窃取也能将损失控制在极小范围,适合作为基础安全层搭配其他方案使用。
- 方案3(闭包隔离Token+仅预定义接口访问):可行性极高,是当前脚本宿主类产品的主流实现方案,具体落地方法如下。
方案3的具体实现方法
1. 闭包封装避免Token全局暴露
不要将Token存储在localStorage、sessionStorage、window属性等第三方脚本可直接访问的位置,将Token封装在主应用私有闭包内,仅通过预定义的代理方法对外提供请求能力:
// 主应用私有作用域,外部无法直接访问内部变量 (() => { // 私有Token,仅当前作用域可访问 const PRIVATE_ACCESS_TOKEN = '用户身份Token' // 预定义暴露给外部的安全请求方法 window.secureApiRequest = async (reqConfig) => { // 前置校验:仅允许访问预定义的合法接口 const ALLOWED_API_PATHS = [ '/api/public/get_script_config', '/api/user/save_script_preference' ] if (!ALLOWED_API_PATHS.includes(reqConfig.url)) { throw new Error('Request API is not allowed') } // 自动注入鉴权头,全程不对外暴露Token const mergedHeaders = { ...reqConfig.headers, Authorization: `Bearer ${PRIVATE_ACCESS_TOKEN}` } return fetch(reqConfig.url, { method: reqConfig.method || 'GET', headers: mergedHeaders, body: reqConfig.body }) } // 冻结暴露的方法,避免被第三方脚本篡改 Object.freeze(window.secureApiRequest) })()
2. 全局请求劫持防止Token泄露
在加载第三方脚本之前,劫持全局的fetch、XMLHttpRequest等请求API,禁止第三方脚本自行在请求头、请求参数中携带敏感信息,同时拦截对存储接口的非法访问:
// 劫持fetch,禁止手动添加Authorization头 const originalFetch = window.fetch window.fetch = (url, config = {}) => { if (config.headers?.Authorization || config.headers?.authorization) { throw new Error('Manual Authorization header setting is not allowed') } return originalFetch(url, config) } Object.freeze(window.fetch)
3. 可选:Web Worker进一步隔离运行环境
如果安全要求更高,可以将第三方脚本完全放在Web Worker中运行,Worker上下文与主页面上下文完全隔离,无法直接访问DOM、window对象和本地存储,所有请求操作必须通过postMessage向主页面申请,由主页面代理完成,彻底切断第三方脚本接触Token的路径。
补充安全优化方案
- 接口侧增加签名校验:服务端除了验证Token,还要验证请求的动态签名,签名由主应用私有逻辑生成,第三方脚本无法伪造,即使Token被窃取也无法调用接口。
- 第三方脚本前置扫描:脚本上架前做静态代码检测,识别窃取敏感信息、发送可疑请求的恶意代码。
- 服务端风控拦截:针对异常请求行为(比如短时间大量请求、非预期IP访问、请求非授权接口)直接触发Token熔断机制。
内容的提问来源于stack exchange,提问作者Autumnlight
相关产品推荐
相关产品推荐

