ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

接口调试利器:手写一键复制Cookie和Token的浏览器扩展

接口调试利器:手写一键复制Cookie和Token的浏览器扩展 简介一款针对前端开发、接口调试与安全测试场景的浏览器扩展工具解决开发中反复手动复制当前网页Cookie、Token、LocalStorage和SessionStorage的低效问题。支持一键识别JWT、Bearer Token等常见Token渐变界面和点击即复制的交互设计使操作更直观。无论是快速登录态注入还是本地存储数据排查都能显著提升效率。资源包为zip压缩格式共6个文件主要包含2个JS逻辑脚本、1个HTML弹窗界面、1个JSON清单配置、1个SVG图标及1份Markdown说明文档整体仅7KB轻量精简、易于安装与二次修改。目前已有1170人学习/下载适合希望快速掌握浏览器插件基础结构或直接拿取工具使用的开发者。通过该工具可清晰了解扩展从manifest配置到内容脚本注入、弹窗交互的完整实现路径同时获得可直接运行的Cookie与Token快捷复制方案便于后续按需调整功能或界面。 做前后端联调、排查线上接口问题的时候我最烦的一件事就是在浏览器DevTools里翻Cookie。调试一个页面要先打开Application面板展开Cookies找到对应域名再一行行找需要的字段右键复制贴到Postman或者curl命令里。如果还要带Token又得去Network面板翻某个请求的Authorization头。一个字段还好遇到多环境切换、多账号测试的场景光复制粘贴就能耗掉小半天。所以我花了一个晚上写了这个CookieToke一键复制插件。标题里的Toke其实就是Token的随手缩写实际做的事就是两件在浏览器工具栏点一下把当前页面的Cookie整体复制出来再把Token也按配置提取出来一并复制。整个过程不用打开DevTools、不用手动筛选字段纯本地处理不经过任何第三方服务器。这个工具适合前端开发、接口调试、测试人员也适合任何一个需要频繁跟浏览器鉴权信息打交道的同学。1. 为什么我专门做了一款一键复制Cookie和Token的小工具1.1 手动复制Cookie的真实成本手动复制这件事儿的成本比很多人想的要高。乍一看就是右键-复制两步但前提是你得先准确定位到Cookie所在的位置。DevTools里Application面板下的Cookies节点会按域名分好多级你得先认出当前接口走的是哪个域名再点开对应站点逐个从上往下找name列。页面的Cookie稍微多一点五六个起步、十几个也很正常你还要在两个字段之间来回看生怕复制串了。遇到Cookie值里嵌了URL编码和签名串那更是灾难。我印象最深的一次是排查线上接口偶发401。同一个页面在测试环境是好的线上却报未登录。手动把线上环境的Cookie复制出来仔细比对之后才发现登录态相关的字段在页面里其实有两个一个是给页面脚本用的一个是HttpOnly的给服务端用的。如果不把这两个一起带上某些接口就会判定为异常。这种场景手动操作特别容易漏所以我决定干脆写个工具把当前页面全部Cookie一次性拿出来这个过程自动化。1.2 为什么我对现成的Cookie扩展不满意Chrome应用商店里已经有不少Cookie相关的扩展我试用过几个整体感受是两极分化。要么权限设计得太重一上来就申请读取全部浏览数据让人不太放心要么界面功能堆得很满打开弹窗还要找半天按钮。还有个更实际的问题是很多扩展常年不更新直接不支持Manifest V3在新版Chromium系浏览器里根本装不上。至于付费的、需要云同步数据的我直接不考虑因为Cookie和Token这类敏感内容最好只在本地处理。另外我的核心诉求其实很简单一键复制、格式可控、纯本地运行。现成工具普遍做不到完全自己说了算。比如我想把Cookie复制成标准的kv; k2v2;格式再顺带把请求头里Authorization的Token提取出来很多严格意义上的Cookie管理扩展根本不碰请求头。与其去适配别人的交互逻辑不如自己写一个。核心代码两三百行主场景完全覆盖后续还能按需改。1.3 书签脚本、油猴脚本为什么都不如插件在动手写之前我其实先排除了两个看起来更轻的选择。第一个是书签脚本也就是把一段javascript:伪协议存成书签点击时在页面里执行。这方案在十年前很好使现在很多站点的CSP直接把这类脚本卡死而且它运行在页面上下文里既拿不到HttpOnly Cookie也访问不了chrome.cookies这类浏览器扩展API。第二个是油猴脚本安装门槛对非技术用户偏高而且油猴在某些系统上还要单独装配套客户端放在团队里推广不现实。浏览器插件就没有这些限制。Manifest V3扩展拥有独立的权限模型声明cookies权限之后可以通过chrome.cookies API读取当前页面的Cookie连HttpOnly标记的也能拿到配合scripting权限还能往页面里注入脚本去读localStoragepopup按钮就是现成的交互入口。对于一键复制鉴权信息这个场景插件方案是效果和成本都最合适的。2. 动手前先搞懂Cookie和Token在浏览器里到底存在哪2.1 为什么浏览器只把这些数据交给了chrome.cookies要理解这个插件先得搞明白chrome.cookies API的工作方式。它并不是去读当前页面内存里的Cookie而是直接调用Chromium内部的Cookie Manager。你传给它一个url或domain参数它会把与这个地址匹配的Cookie全部列出来返回数组里每个Cookie对象除了name和value还带domain、path、secure、httpOnly、sameSite等字段。这里有个容易被忽略的点chrome.cookies.getAll里的url匹配规则和浏览器发送请求时的Cookie匹配规则不完全一样。传入url时Chrome会按domain加path来匹配并且secure的Cookie只在https地址下返回。所以想完整覆盖当前页面的所有Cookie正确做法是取当前标签页的完整URL后原样传给API让浏览器自己去做匹配不要手动只传域名。用起来其实相当简单获取当前标签页的URL后调用一次getAll就行。2.2 Token往往不在Cookie里得按四种藏身处分别处理很多刚接触接口调试的同学会把Cookie和Token混为一谈但它们其实不是一个层面的东西。Cookie只是浏览器保存文本片段的一种机制特点是每次请求都会自动带上它而Token通常指的是登录认证用的凭证最典型的是JWT可能放在Cookie里也可能放在localStorage、sessionStorage甚至只出现在请求头Authorization字段里。这直接决定了一键复制不能只处理一种来源。实际开发中Token的藏身之处大概有四类Token放在Cookie里常见于服务端下发、设置HttpOnly的场景直接走chrome.cookies就能拿到。Token放在localStorage或sessionStorage里很多单页应用的登录态都在这要用chrome.scripting.executeScript往目标页面注入脚本去读storage。Token只出现在请求头Authorization里这是最隐蔽的一种要通过chrome.webRequest.onBeforeSendHeaders去监听请求从requestHeaders里取。Token只存在于页面JS变量的内存中这种情况插件很难自动处理基本只能靠断点手动复制。我自己写插件时的策略很简单先快速扫一遍Cookie里有没有命中token关键字没有就往页面注入一段脚本读localStorage再没有就提示用户手动从Network面板复制。为什么强调这个顺序因为注入脚本会有页面副作用严格环境下的CSP可能拦截注入还可能与页面自己的代码冲突而chrome.cookies API是扩展特供通道几乎不会被打断。顺序排好之后插件的自动识别成功率能稳定在九成以上。3. 一步步写出来manifest配置、popup页面与复制逻辑3.1 manifest.json里最容易被忽略的三个权限整个插件不需要后台常驻的复杂逻辑所以manifest可以写得非常精简。核心是把权限声明到位尤其是cookies和host_permissions少一个Chrome都会在运行时静默失败而不是给你一个明确的报错。{ manifest_version: 3, name: Cookie Token 一键复制, version: 1.0.0, description: 一键复制当前页面的Cookie和Token方便接口调试, permissions: [cookies, activeTab, scripting, clipboardWrite, storage], host_permissions: [all_urls], action: { default_popup: popup.html, default_title: Cookie Token 一键复制 }, options_page: options.html }逐个解释一下权限的用途。cookies是读取Cookie的必备权限没有它chrome.cookies整个命名空间都不可用。activeTab很关键它让用户在点击扩展图标的瞬间扩展自动获得当前标签页的临时访问权限这样popup里就能直接读取tab.url也能对该标签页执行脚本。scripting用于注入脚本读localStorageclipboardWrite用于写剪贴板storage则用来存用户配置。这里最容易被忽略的是host_permissions。很多新手只写了cookies权限就开搞结果发现getAll总是返回空。原因就是host_permissions没有覆盖目标域名cookies API在身份校验时被拦住了。最简单省事的方式就是写成all_urls配合activeTab的临时授权既能满足大部分场景也不会在安装时把读取所有网站数据这个警告暴露得太难看。如果你发现popup里tab.url总是空的记得在permissions里补一个tabs权限。3.2 popup页面和两个复制按钮的逻辑popup.html不需要花哨两个按钮加一个状态提示区就够了。我自己连图标都懒得画直接让Chrome用默认的字母图标。!DOCTYPE html html langzh-CN head meta charsetUTF-8 titleCookie Token 一键复制/title style body { width: 260px; margin: 0; padding: 16px; font-family: sans-serif; } button { width: 100%; margin: 6px 0; padding: 10px; border: none; border-radius: 6px; cursor: pointer; font-size: 14px; color: #fff; } #copyCookie { background: #4e7cf5; } #copyToken { background: #00b578; } #status { margin-top: 10px; font-size: 13px; color: #666; word-break: break-all; } /style /head body button idcopyCookie复制当前页面 Cookie/button button idcopyToken复制 Token/button div idstatus/div script srcpopup.js/script /body /htmlpopup.js是整个工具的核心逻辑分成三块拿当前标签页的URL、调chrome.cookies读取Cookie、把结果写进剪贴板。写的时候要注意popup打开的瞬间就要去拿tab信息如果用户点的是空白标签页或者chrome://开头的页面直接提示请在网页页面使用。async function getCurrentTab() { const [tab] await chrome.tabs.query({ active: true, currentWindow: true }); return tab; } async function copyText(text) { if (navigator.clipboard window.isSecureContext) { await navigator.clipboard.writeText(text); } else { const textarea document.createElement(textarea); textarea.value text; document.body.appendChild(textarea); textarea.select(); document.execCommand(copy); document.body.removeChild(textarea); } } document.getElementById(copyCookie).addEventListener(click, async () { const status document.getElementById(status); const tab await getCurrentTab(); if (!tab?.url || !/^https?:/.test(tab.url)) { status.textContent 请在网页页面使用; return; } const cookies await chrome.cookies.getAll({ url: tab.url }); if (!cookies.length) { status.textContent 未获取到 Cookie; return; } const text cookies.map(c ${c.name}${c.value}).join(; ); await copyText(text); status.textContent 已复制 ${cookies.length} 个 Cookie; }); document.getElementById(copyToken).addEventListener(click, async () { const status document.getElementById(status); const tab await getCurrentTab(); if (!tab?.url) return; const cookieText (await chrome.cookies.getAll({ url: tab.url })) .map(c ${c.name}${c.value}).join(; ); const tokenKeys [token, access_token, authorization, auth, jwt]; let token tokenKeys .map(k new RegExp((?:^|;\\s*)${k}([^;]), i).exec(cookieText)) .filter(Boolean)[0]?.[1]; if (!token) { try { const results await chrome.scripting.executeScript({ target: { tabId: tab.id }, func: () { const keys [token, access_token, authorization, auth, jwt]; for (const k of keys) { for (let i 0; i localStorage.length; i) { const key localStorage.key(i); if (key.toLowerCase().includes(k)) { const val localStorage.getItem(key); if (val) return val; } } } return null; } }); token results?.[0]?.result; } catch (e) { // CSP 或页面环境不允许时静默忽略 } } if (!token) { status.textContent 未能自动识别 Token请检查页面存储方式; return; } await copyText(token); status.textContent Token 已复制; });复制Token时我用了两层策略。第一层在Cookie里找常见的关键字包括token、access_token、authorization、auth、jwt第二层如果找不到再注入脚本去遍历localStorage的key只要key名包含这些关键字之一就把对应的value取出来。这个遍历逻辑写得比较宽泛因为不同系统的命名习惯差很多有的叫accessToken有的叫user_token有的干脆叫auth宽泛匹配才能真正提升命中率。3.3 剪贴板写入别只依赖navigator.clipboard早期版本我直接用navigator.clipboard.writeText结果在部分用户机器上发现复制失败。原因有两个一是popup页面在特定窗口状态下不是安全上下文Clipboard API直接不可用二是有些系统的快捷键管理软件会抢占剪贴板焦点导致写入静默失败。所以我加了回退方案用隐藏textarea加document.execCommand(copy)兼容性一下就上来了。现在的浏览器虽然推荐Clipboard API但execCommand在扩展场景里依然是可靠的兜底。还有个小细节popup窗口在点击按钮后不要立即关闭最好留出几百毫秒显示已复制状态否则用户会怀疑到底复制没复制。面板的关闭时机控制在用户点击页面其他地方或者按Esc体验会自然很多。4. 四类实测踩坑HttpOnly、getAll空返回、请求头Token与MV3限制4.1 HttpOnly Cookie页面脚本看不见扩展却能读第一次实测我就遇到一个很典型的坑用document.cookie去打印页面Cookie结果返回的字段比DevTools里少了一大截。差出来的那几个都带有httpOnly标记。HttpOnly是服务端在Set-Cookie时加的属性作用就是禁止JavaScript访问防止XSS攻击把Cookie偷走。这本来是好事但对调试工具来说就很麻烦。好在chrome.cookies API不走页面脚本那套它是浏览器暴露给扩展的独立通道所以在扩展里读取HttpOnly Cookie毫无压力。这个能力也是我最终选择插件方案的重要理由。需要提醒的是设计的时候要有意识地保留httpOnly字段信息虽然一键复制时会忽略它但后续如果做按类型筛选复制的功能它能帮你区分哪些是页面层的、哪些是服务端层的。4.2 host_permissions没写全getAll会静默返回空这大概是插件开发里最隐晦的坑了。如果你在manifest里只声明了permissions: [cookies]而忘记写host_permissions或者host_permissions只写了某个具体域名那么对未授权域名调用chrome.cookies.getAll不会报错而是直接返回一个空数组。我第一次遇到时检查了半天代码最后是翻文档才确认是权限范围的问题。排查思路其实很简单先看manifest里host_permissions是否覆盖了你调试的域名最简单的就是写成all_urls。权限范围给得太窄Cookie数据接口直接不让你碰这是Chrome的安全设计逻辑并不是bug。另外打开chrome://extensions页面点击对应扩展的Service Worker链接在后台调试控制台里能看到一些权限相关的警告排查问题时会很有帮助。4.3 Authorization请求头里的TokenMV3只允许看、不允许改这是整个项目里最受限制的部分。有些后台系统的Token既不在Cookie也不在localStorage而是每次发请求时由前端某个模块动态拼进Authorization头里。要自动提取这类Token就得在插件里用chrome.webRequest.onBeforeSendHeaders监听请求在回调里读取requestHeaders。先说结论读取可以修改不行。Manifest V3已经收走了阻塞式拦截请求头的能力只保留观察能力。如果你只是想拿到Authorization字段并复制下来声明webRequest权限并监听请求就够如果想改请求头就得换declarativeNetRequest去配置规则那就不是这个轻量插件该干的事了。实际体验还会遇到两个问题。一是监听事件会持续触发对性能有影响不要一直开着最好在popup里加个开关需要提取Token时才开启监听。二是部分站点对Header做了同源校验跨域请求根本不会携带Authorization你看到的请求头自然就没有这时候要在界面上提示用户别在跨域场景下测。4.4 MV3的service worker休眠问题怎么绕开Manifest V3把后台页面换成了service worker它会休眠。如果你把所有逻辑都放在service worker里第一次点击扩展图标时事件传递要等worker唤醒偶尔会有半秒延迟体验很伤。这个项目根本不需要常驻后台所以我把所有复制逻辑都放在popup里点开即用、关掉即无状态省去很多生命周期的心智负担。如果你的插件一定要在后台做监控、做自动提取记得在声明周期里处理onInstalled、onStartup这些事件避免service worker被回收之后注册的事件失效。MV3这种用完即走的模型和popup这种临时UI其实是绝配。5. 从自用脚本到团队效率工具的三个升级方向5.1 复制格式可配置团队不同角色才能都顺手第一版写完之后我先内部用了两天发现不同人的口味确实不一样。我自己喜欢标准的kv;格式复制到Postman和curl里不用二次处理后端同事希望输出JSON因为他要直接塞到脚本的配置文件里还有测试同学只想要一个纯Token值方便填到接口测试平台。所以我在options.html里加了格式化模板选项目前支持三种格式kv分号分隔、JSON对象、仅值。选择结果通过chrome.storage.sync存起来popup打开时读一次配置按模板生成结果。chrome.storage.sync有个好处同一个账号在不同电脑上会同步配置办公室的电脑和家里的电脑不用重复设置。实现也很简单就是在popup读取配置的key value时根据当前格式重新组装字符串。5.2 多环境、多账号场景下的Cookie映射到了团队合作层面最常见的需求是测试环境切来切去。很多后端项目有dev、qa、staging三套环境域名不同Cookie也不一样。手动操作时经常有人把预发布环境的Cookie复制到开发环境上导致排查问题时数据对不上非常浪费时间。我给插件加了一个简单的映射表在配置页里维护一个环境域名列表复制Cookie时popup里会多一个下拉框选中哪个环境复制出来的内容就自动带上对应环境的说明字段。核心目的不是去伪造任何身份而是让调试时要带哪些字段、对应哪个环境一目了然减少低级错误。这个功能做好之后团队里再没出现过用错环境Cookie的尴尬事。5.3 顺手生成curl命令测试同学也能用最后一个我特别推荐的扩展方向是生成curl命令。Cookie和Token都拿到之后再结合页面的URL完全可以在popup里直接拼出一条带鉴权的curl命令curl -H Cookie: ... -H Authorization: Bearer ... https://api.example.com/xxx。调试后端接口时这条命令可以直接扔到终端里跑比打开Postman还快。实现也不复杂当前页面的URL、Cookie、Token都已经在手里了拼字符串就好。唯一要注意的是把双引号转义处理干净Cookie里经常有引号或特殊字符漏一个就导致命令解析失败。我在输出前统一做一次escape处理实测稳定很多。这个功能团队内部反馈特别好很多不熟悉DevTools的测试同学靠这个功能把日常接口排查效率提了一倍。工具做得足够简单大家才真的愿意用起来。我自己实际用下来的体会是做这个插件的初衷很朴素就是联调太烦了想点一下能把Cookie和Token都拿全。真正落地之后发现花在让格式适合自己工作流上的时间比写插件本身还多。很多工具之所以不好用不是功能不够多而是不理解使用者的输出格式习惯。最后分享一个小技巧我把复制Cookie按钮绑定到了扩展图标的单击事件上直接点击图标就执行复制操作再点一下弹出面板看状态。这个改动看似很小但实际使用频率立刻高了很多。如果你也打算自己写一个类似的效率工具建议从最频繁的操作入手先跑通最小闭环再往上加功能比我一开始就想着做全功能要靠谱得多。本文还有配套的精品资源点击获取
返回列表