Tampermonkey脚本import模块违反CSP指令如何解决?
解决Tampermonkey脚本中导入ESM模块的CSP限制问题
问题根源
目标网站(知乎)的**内容安全策略(CSP)**限制了脚本加载来源,禁止从esm.sh域名加载脚本,直接使用import()或通过GM_addElement添加模块类型脚本都会触发CSP拦截。
可行解决方案
方案1:通过GM_xmlhttpRequest获取模块代码,用Blob URL注入
利用Tampermonkey的GM_xmlhttpRequest不受页面CSP限制的特性,拉取模块代码后转换为Blob URL注入(知乎CSP允许blob:来源):
// ==UserScript== // @name xxxxxx // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @include *://*.zhihu.com/* // @grant GM_xmlhttpRequest // ==/UserScript== GM_xmlhttpRequest({ method: 'GET', url: 'https://esm.sh/octokit', responseType: 'text', onload: (res) => { // 将模块代码转为Blob对象 const blob = new Blob([res.responseText], { type: 'application/javascript' }); const blobUrl = URL.createObjectURL(blob); // 注入模块脚本 const moduleScript = document.createElement('script'); moduleScript.type = 'module'; moduleScript.src = blobUrl; // 模块加载完成后执行业务逻辑 moduleScript.onload = () => { const usageScript = document.createElement('script'); usageScript.type = 'module'; usageScript.textContent = ` import { Octokit, App } from '${blobUrl}'; // 这里编写你的业务代码 const octokit = new Octokit(); console.log('Octokit 加载完成:', octokit); `; document.head.appendChild(usageScript); URL.revokeObjectURL(blobUrl); // 释放Blob资源 }; document.head.appendChild(moduleScript); } });
方案2:导入打包后的IIFE版本模块
使用esm.sh的打包功能,将模块转换为IIFE格式(自动挂载到全局window对象),避免模块类型脚本的CSP限制:
// ==UserScript== // @name xxxxxx // @namespace http://tampermonkey.net/ // @version 0.1 // @description try to take over the world! // @author You // @include *://*.zhihu.com/* // @grant GM_addElement // ==/UserScript== // 导入打包后的IIFE版本,模块会挂载到window GM_addElement('script', { src: 'https://esm.sh/octokit?bundle', type: 'text/javascript' }); // 等待脚本加载完成后使用模块 window.addEventListener('load', () => { const { Octokit, App } = window; const octokit = new Octokit(); console.log('Octokit 加载完成:', octokit); });
内容的提问来源于stack exchange,提问作者hrdom
相关产品推荐
相关产品推荐

