开发一个 Chrome DevTools 接口解密插件
About
8
min read
(
94
Words
)
Reads
在金融项目中,通常接口url和参数都会进行加密,所以在调试的时候,Network 面板里看到的全是密文,调试起来非常痛苦。这篇文章介绍我开发的 xxx Network —— 一个 Chrome DevTools 插件,能够自动拦截并解密 xxx 系统的加密接口,让调试回归正常。
背景
xxx 系统的接口采用 AES-CBC 加密,请求体、响应体以及真实路径都是密文。打开 Chrome DevTools 的 Network 面板,看到的是这样的内容:
1 2 3
| request body: "U2FsdGVkX1+..." response body: "U2FsdGVkX1+..." x_x_path: "U2FsdGVkX1+..."
|
每次调试都要手动解密,效率极低。于是我决定写一个 DevTools 插件,把解密过程自动化。
技术方案
整体架构分两层:
- Chrome Extension 层:利用
chrome.devtools.network API 监听网络请求,用 chrome.scripting.executeScript 从页面 localStorage 读取加密密钥(xxxSalt)。
- 前端 UI 层:用 Vue 3 + Element Plus 构建 DevTools 面板,展示解密后的请求列表和响应内容,并支持语法高亮。
1 2 3 4 5 6 7 8 9 10
| xxx-network/ ├── manifest.json # 插件配置 ├── devtools.html # DevTools 入口页 ├── devtools.js # 注册自定义面板 ├── xxx-network/ # Vue3 前端项目 │ └── src/ │ ├── util.ts # AES 解密核心逻辑 │ └── components/ │ └── Main.vue # 主界面 └── chrome-plugin-xxx-network.sh # 打包脚本
|
核心:AES-CBC 解密
加密算法是 AES-CBC + PKCS7 填充,IV 固定为 xxx_mgr_item_a,密钥由 xxxSalt 经过一次解密得到(两层嵌套)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function getIvAndkey(xxxSalt: string, key: string) { return { iv: "xxx_mgr_item_a", key: decrypt(xxxSalt, { iv: "xxx_mgr_item_a", key }), }; }
function decrypt(str: string, { iv, key }: { iv: string; key: string }) { if (str.startsWith("{")) return formatJSONString(str); str = str.replace(/"/gi, ""); const decrypted = CryptoJS.AES.decrypt(str, CryptoJS.enc.Utf8.parse(key), { iv: CryptoJS.enc.Utf8.parse(iv), padding: CryptoJS.pad.Pkcs7, mode: CryptoJS.mode.CBC, }); const result = decrypted.toString(CryptoJS.enc.Utf8).trim(); if (result.startsWith("{")) return formatJSONString(result); return result; }
|
generate 函数把一条原始网络请求转换成可读的结构:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export const generate = (network: any, { content, salt }) => { const token = network.request.headers.find((h) => ["xxxtoken", "token"].includes(h.name.toLowerCase()), ); const xxPath = network.request.headers.find( (h) => h.name.toLowerCase() === "x_x_path", );
const { iv, key } = getIvAndkey(salt, token?.value);
return { status: network.response.status, url: network.request.url, path: decrypt(xxPath?.value, { iv, key }) || network.request.url, params: JSON.stringify( decrypt(network.request.postData?.text, { iv, key }), ), reponseObj: decrypt(content, { iv, key }), }; };
|
监听网络请求
在 Main.vue 的 onMounted 中,通过 chrome.devtools.network.onRequestFinished 监听请求完成事件,过滤出 /manager 路径下的接口,再用 chrome.scripting.executeScript 注入脚本从页面读取 xxxSalt:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| chrome.devtools.network.onRequestFinished.addListener((request) => { if (!request.request.url.includes("/manager")) return;
request.getContent((content) => { chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => { chrome.scripting .executeScript({ target: { tabId: tabs[0].id }, function: () => localStorage.getItem("xxxSalt"), }) .then(([{ result: salt }]) => { requests.push(generate(request, { salt, content })); }); }); }); });
|
UI 界面
面板左侧是请求列表,展示状态码、URL、解密后的真实路径和请求参数;右侧点击 “Response” 后显示格式化的 JSON 响应,通过 Prism.js 做语法高亮(字符串绿色、数字蓝色、布尔值红色)。
操作按钮只有两个,保持简洁:
- Clear All:清空所有请求记录
- Copy Response:复制当前响应内容到剪贴板
构建与安装
1 2 3 4 5 6 7 8
| cd xxx-network npm i && npm run dev
npm run build cd .. bash ./chrome-plugin-xxx-network.sh
|
脚本会把 Vite 构建产物、manifest.json、devtools.js 等文件整合到 chrome-xxx-network/ 目录,在 Chrome 的 chrome://extensions/ 页面加载该目录即可。
manifest.json 关键配置:
1 2 3 4 5 6
| { "manifest_version": 3, "permissions": ["tabs", "activeTab", "scripting"], "devtools_page": "devtools.html", "host_permissions": ["http://localhost/*", "*://*.xxx.com/*"] }
|
host_permissions 限定了插件生效的域名,避免对无关站点产生影响。
小结
整个插件的核心思路很清晰:DevTools API 拦截请求 → 从页面上下文读取密钥 → AES 解密 → Vue UI 展示。代码量不大,但解决了实际痛点。
如果你的项目也有类似的接口加密场景,可以参考这个思路,把解密逻辑替换成自己的算法,快速定制一个专属的 DevTools 调试面板。