1. 项目概述用FiddlerScript在请求链路中“悄悄塞进”登录凭证你有没有遇到过这样的场景测试一个Web系统时每次都要手动输入账号密码、点登录、等跳转、再刷新页面——重复十次手酸眼花还容易输错验证码或者写自动化脚本时发现登录接口做了强校验比如时间戳随机token前端加密绕不开前端逻辑硬啃JS又耗时费力又或者想快速验证某个登录后接口的响应行为但不想每次都走完整登录流程这时候FiddlerScript 就不是个“抓包工具插件”而是一把能精准切入HTTP流量管道的手术刀。这个项目标题里三个短语其实是一体三面“FiddlerScript 注入cookie实现自动登录”是技术手段“Fiddler实现免登陆”是最终效果“浏览器通代理实现自动登录”是落地路径。核心逻辑非常朴素不改前端、不碰后端、不写新服务只在浏览器发出的每一个HTTP请求离开本地前由Fiddler动态补上合法有效的Session Cookie。它绕开了所有登录表单交互和前端鉴权逻辑直接复用已有的、服务器认可的身份凭证。这不是破解而是对现有认证体系的一次“合法借用”——前提是你已经通过正规方式获得过一次有效登录态比如手动登录一次或从其他可信渠道拿到cookie值。我最早在某高校实验室做API压力测试时用上这招。当时要压测一个教务系统的课表查询接口但该系统登录态有效期仅30分钟且登录接口带RSA前端加密用Selenium跑一轮登录要40秒以上而压测需要每秒发起200请求。我们试过保持Session对象复用但跨线程不稳定也试过提取登录响应里的Set-Cookie头手动构造结果发现Cookie里有个叫_session_sig的字段每次登录都变且服务端会校验其HMAC签名。最后就是靠FiddlerScript在每个请求发出前从本地安全存储里读取最新有效的cookie字符串原样注入到Request Header里。实测下来整个压测过程持续2小时零登录中断QPS稳定在185左右。这种方案特别适合测试人员、前端联调工程师、以及需要高频调用内部系统的运维同学——它不要求你懂后端架构也不依赖开发配合只要你会看Fiddler的Inspectors面板就能当天上手。提示这个方案的本质是“客户端侧会话劫持”它完全运行在你的本地机器上所有操作只影响你自己的浏览器流量不触碰服务器代码也不干扰其他用户。它的安全边界非常清晰cookie值必须来自你本人合法获取的会话不能盗用他人凭证也不能用于越权操作。这是技术中立性与使用合规性的基本分水岭。2. 核心原理拆解为什么FiddlerScript能“无感”注入Cookie要真正用好这个功能不能只停留在“复制粘贴一段脚本”的层面。得明白FiddlerScript到底在HTTP协议栈的哪个环节起作用、它修改的是请求的哪一部分、为什么服务端会认这个“假造”的Cookie。这背后涉及Fiddler的代理机制、HTTP协议的Header结构、以及Web会话管理的基本范式。2.1 Fiddler作为中间人代理的天然优势Fiddler不是简单的网络监听器而是一个可编程的HTTP/HTTPS代理服务器。当你把浏览器代理设为127.0.0.1:8888所有HTTP请求不再直连目标网站而是先发给本机的Fiddler进程Fiddler收到后可以查看、修改、阻断、重发这个请求然后再转发给真正的服务器。这个“中间人”位置给了我们两个关键能力一是能看到明文请求即使HTTPSFiddler也能通过根证书解密二是能在请求离开发出前的最后一刻做手脚。FiddlerScript正是利用了这个“最后一刻”。它不是一个独立运行的脚本而是嵌入在Fiddler主进程中的JScript.NET引擎。每当一个请求即将被转发OnBeforeRequest事件或一个响应即将返回给浏览器OnBeforeResponse事件时Fiddler会触发对应的脚本函数。我们就是在OnBeforeRequest里动手——此时请求对象oSession已经构建完成包含了URL、Method、Headers、Body等全部信息但还没发出去。我们修改它的oSession.oRequest.headers就等于在数据包真正打包飞出去之前往信封里塞了一张新纸条。2.2 Cookie的双重身份既是客户端存储也是服务端信任凭证很多人以为Cookie只是浏览器存的一个小字符串其实它在HTTP协议里扮演着双重角色。从客户端看它是document.cookie里可读写的键值对但从协议角度看它是HTTP Request Header里一个叫Cookie的字段格式为key1value1; key2value2。服务端收到这个Header会解析其中的Session ID比如JSESSIONIDabc123然后去自己的Session存储内存、Redis、数据库里查这个ID对应的身份信息。如果查到了就认为“这个请求来自已登录用户”。所以注入Cookie的本质就是让Fiddler在每个请求的Header里强制加上一行Cookie: JSESSIONIDabc123; _user_tokenxyz789。服务端看到这个Header和它自己生成的Session记录一比对完全匹配自然就放行。这里的关键在于服务端只认Cookie值本身不关心这个值是怎么来的。它不会去检查“这个Cookie是不是浏览器自己从Set-Cookie头里存下来的”也不会验证“这个请求是不是从登录页跳转过来的”。只要你能提供正确的Session ID它就信你。2.3 为什么不用改浏览器或装插件代理层修改的不可见性有人会问既然要加Header为什么不在浏览器里用开发者工具Console手动fetch(url, {headers:{...}})因为那只能发单次请求无法覆盖整个页面的所有资源加载图片、CSS、AJAX。也有人想能不能写个Chrome扩展用webRequestAPI拦截并修改当然可以但要走应用商店审核、要处理HTTPS证书、还要适配不同浏览器内核。而FiddlerScript的妙处在于它工作在TCP/IP模型的应用层代理位置对上层浏览器完全透明。你用Chrome、Edge、Firefox甚至curl命令行只要代理指向Fiddler所有流量都会被统一处理。你不需要改任何一行前端代码不需要装额外插件甚至不需要重启浏览器——改完脚本CtrlS保存下个请求立刻生效。这种“无侵入式”的改造能力正是它在真实工程场景中难以替代的原因。注意Fiddler默认只解密HTTP流量。要处理HTTPS必须在Fiddler Options里勾选“Decrypt HTTPS traffic”并安装Fiddler Root Certificate。这是合法的本地解密原理是Fiddler充当了你电脑上的“可信中间CA”浏览器信任它所以它能解密后再加密转发。这个步骤必不可少否则你看到的HTTPS请求Body全是乱码也无法准确识别登录后的Set-Cookie响应。3. 实操全流程从零开始配置FiddlerScript注入Cookie现在我们把原理落地。下面是一个完整的、经过我多次实测验证的操作流程从安装Fiddler到写出可运行的脚本再到日常维护。每一步都附带“为什么这么做”的解释避免你成为只会复制粘贴的工具人。3.1 环境准备Fiddler安装与HTTPS解密配置第一步永远是环境。Fiddler官方版Telerik Fiddler Classic是免费的去官网下载最新Installer即可。安装过程无脑下一步但有两个关键设置必须在首次启动后立即完成启用HTTPS解密打开Fiddler → Tools → Options → HTTPS tab → 勾选“Decrypt HTTPS traffic”。这时会弹出证书安装提示点“Yes”让Fiddler把它的根证书安装到Windows证书管理器的“受信任的根证书颁发机构”里。这一步完成后你才能在Inspectors → TextView里看到HTTPS请求的明文URL和响应Body。如果不做你只能看到CONNECT www.example.com:443 HTTP/1.1这种隧道建立请求对调试毫无帮助。配置浏览器代理以Chrome为例打开设置 → 高级 → 系统 → 打开计算机的代理设置 → LAN设置 → 勾选“为LAN使用代理服务器”地址填127.0.0.1端口填8888Fiddler默认端口。保存后Chrome所有流量就会经Fiddler中转。验证方法打开Fiddler再访问任意HTTPS网站如https://httpbin.org/get如果Fiddler列表里出现绿色状态码200的请求说明代理成功。提示如果你用的是公司内网或某些特殊网络环境可能需要在Fiddler Options → Connections tab里勾选“Allow remote computers to connect”并关闭防火墙相关端口。不过绝大多数个人开发场景本地回环地址127.0.0.1就够了无需开放远程连接。3.2 获取合法Cookie三种可靠来源与安全存储注入的前提是有“真货”。Cookie不是随便编的字符串它必须是服务端签发的有效凭证。我总结了三种最常用、最可靠的获取方式按推荐度排序方式一手动登录后实时捕获最推荐新手在Fiddler开启状态下用已配置代理的浏览器访问登录页输入账号密码点击登录。登录成功后立刻在Fiddler左侧会话列表里找到那个返回302 Found或200 OK的登录请求通常是POST/login。双击它 → 切换到Inspectors → Headers → Response → 找到Set-Cookie字段。这里通常有多行比如Set-Cookie: JSESSIONIDABC123DEF456; Path/; HttpOnly Set-Cookie: _user_tokenxyz789abc012; Domain.example.com; Path/; Secure; HttpOnly复制这两行的value部分即JSESSIONIDABC123DEF456; _user_tokenxyz789abc012这就是你要注入的完整Cookie字符串。注意HttpOnly标记意味着JavaScript无法读取但这对FiddlerScript没影响因为它工作在HTTP层不依赖JS。方式二从浏览器开发者工具导出适合多Cookie场景按F12打开DevTools → Application → Cookies → 选择对应域名 → 右键“Copy All Cookies”。粘贴出来是一行JSON格式需要简单处理把{name:JSESSIONID,value:ABC123}这种转换成JSESSIONIDABC123多个用分号连接。这种方式适合Cookie数量多、有复杂Domain/Path属性的系统。方式三从已有自动化脚本中提取适合CI/CD集成如果你已经有Python Requests写的登录脚本可以在登录成功后打印response.cookies或session.cookies.get_dict()得到字典后用; .join([f{k}{v} for k,v in cookies_dict.items()])拼成字符串。这种方式可编程适合把FiddlerScript集成进持续测试流水线。安全存储建议不要把Cookie明文写在FiddlerScript文件里。我习惯建一个本地文本文件C:\fiddler_cookies\myapp.txt里面只存一行Cookie字符串。脚本里用System.IO.File.ReadAllText(C:\fiddler_cookies\myapp.txt)读取。这样既方便更新改文本文件就行又避免敏感信息硬编码在脚本中。3.3 编写核心FiddlerScript精准匹配目标域名与路径FiddlerScript的编辑入口在Fiddler → Rules → Customize Rules。这会打开一个名为CustomRules.js的文件它是Fiddler的全局脚本。我们主要修改两个函数static function OnBeforeRequest(oSession: Session)请求发出前触发我们在这里注入Cookie。static function OnBeforeResponse(oSession: Session)响应返回前触发可用于自动刷新Cookie高级用法后面详述。下面是精简、健壮、可直接运行的核心代码段已去除所有注释实际使用时请保留static function OnBeforeRequest(oSession: Session) { // 1. 定义目标域名白名单避免误注入到其他网站 var targetHosts [example.com, staging.example.com, localhost:3000]; // 2. 检查当前请求是否属于目标域名 var hostMatch false; for (var i 0; i targetHosts.length; i) { if (oSession.host.toLowerCase().indexOf(targetHosts[i].toLowerCase()) -1) { hostMatch true; break; } } // 3. 只对目标域名且非登录/登出路径的请求注入Cookie if (hostMatch !oSession.url.toLowerCase().includes(/login) !oSession.url.toLowerCase().includes(/logout) !oSession.url.toLowerCase().includes(/auth)) { // 4. 从本地文件读取Cookie字符串路径按你实际存放位置修改 try { var cookieStr System.IO.File.ReadAllText(C:\fiddler_cookies\myapp.txt).Trim(); if (cookieStr.length 0) { // 5. 移除请求中原有的Cookie Header防止重复 oSession.oRequest.headers.Remove(Cookie); // 6. 添加新的Cookie Header oSession.oRequest.headers.Add(Cookie, cookieStr); } } catch(e) { // 7. 文件读取失败时写日志到Fiddler状态栏便于排查 oSession[ui-backcolor] orange; FiddlerApplication.Log.LogString(ERROR: Failed to read cookie file. Check path and permissions.); } } }这段代码的每一行都有明确意图第1步定义白名单这是安全底线。没有这步你刷微博时也可能被注入教务系统的Cookie导致奇怪的403错误。第2步用indexOf而非全等匹配是为了兼容子域名如api.example.com也匹配example.com。第3步排除/login等路径避免登录请求本身被注入旧Cookie造成循环或冲突。第4-6步是核心动作先清空原有Cookie再写入新值。必须用Remove再Add不能直接Add否则会变成Cookie: old; new服务端可能只认第一个。第7步的日志写法很实用oSession[ui-backcolor] orange会让这一行会话在Fiddler列表里高亮为橙色一眼就能看到哪次请求出了问题。3.4 进阶技巧自动刷新Cookie与多账号切换上面的脚本解决了“注入”但没解决“保鲜”。Cookie会过期手动更新太麻烦。我们可以利用OnBeforeResponse事件在每次收到包含Set-Cookie的响应时自动提取并更新本地文件。static function OnBeforeResponse(oSession: Session) { // 检查响应头里是否有Set-Cookie且是目标域名 if (oSession.oResponse.headers.Exists(Set-Cookie) (oSession.host.toLowerCase().indexOf(example.com) -1)) { // 提取所有Set-Cookie值合并成一行 var newCookie ; var setCookieHeaders oSession.oResponse.headers[Set-Cookie].split(\n); for (var i 0; i setCookieHeaders.length; i) { var line setCookieHeaders[i].trim(); if (line.length 0 line.indexOf(Set-Cookie:) 0) { // 去掉Set-Cookie:前缀取等号前的部分如JSESSIONID... var cookiePart line.substring(11).split(;)[0].trim(); if (cookiePart.length 0) { if (newCookie.length 0) newCookie ; ; newCookie cookiePart; } } } // 写入本地文件追加时间戳便于审计 if (newCookie.length 0) { var now new Date(); var logLine [ now.toISOString() ] Updated: newCookie \r\n; System.IO.File.AppendAllText(C:\fiddler_cookies\myapp_log.txt, logLine); System.IO.File.WriteAllText(C:\fiddler_cookies\myapp.txt, newCookie); // 在Fiddler状态栏显示更新成功 FiddlerApplication.Log.LogString(INFO: Cookie auto-updated at now.toLocaleTimeString()); } } }这个功能的价值在于你只需要第一次手动登录之后所有后续请求只要服务端返回了新的Set-Cookie比如续期、换TokenFiddler就会自动捕获并覆盖本地文件。你完全不用管它就像有个隐形助手在后台帮你续杯。至于多账号切换我用的是“文件名切换法”。建多个cookie文件user_a.txt,user_b.txt,admin.txt然后在OnBeforeRequest里加一个全局变量var currentAccount user_a;读取时用C:\fiddler_cookies\ currentAccount .txt。切换账号只需改这一行变量CtrlS保存脚本下次请求立即生效。比在脚本里写一堆if-else判断URL参数清爽得多。4. 关键细节与避坑指南那些文档里不会写的实战经验写了三年FiddlerScript踩过的坑比看过的文档还多。下面这些细节都是我在某跨平台系统联调、某图像处理Demo压测、某金融风控后台测试中用血泪换来的经验。它们不写在官方手册里但能让你少走三个月弯路。4.1 Cookie属性陷阱Domain、Path、Secure、HttpOnly的真实影响你以为把JSESSIONIDabc123塞进去就万事大吉错。Cookie Header里藏着四个关键属性任何一个不匹配服务端就可能拒绝Domain指定了Cookie生效的域名范围。比如Domain.example.com表示www.example.com、api.example.com、staging.example.com都能用。但如果服务端Set-Cookie时写的是Domainwww.example.com那么api.example.com的请求里塞这个Cookie服务端会直接忽略。解决方案在OnBeforeRequest里注入时不要写Domain属性只写keyvalue。因为浏览器原生Cookie机制会根据当前请求URL自动计算Domain而Fiddler注入的Header是“裸值”服务端只认value不校验Domain。Path指定了Cookie生效的URL路径前缀。Path/admin的Cookie只会在/admin/user、/admin/api等请求中发送。如果你注入的Cookie Path是/但服务端期望的是/app它可能不认。对策同样注入时只写value不写Path。服务端校验的是Session ID本身不是Path。Secure表示这个Cookie只能通过HTTPS传输。如果你在HTTP站点http://localhost:3000上注入了一个带Secure标记的Cookie现代浏览器会直接丢弃它Fiddler也无能为力。所以从HTTPS站点捕获的Cookie如果要用于HTTP开发环境必须手动去掉Secure标记。我的做法是在读取cookie文件后用正则cookieStr.replace(/;\s*Secure/gi, )清除。HttpOnly这个标记只影响JavaScript能否读取对FiddlerScript完全无感。你可以放心注入服务端照单全收。实操心得我写了个小工具函数专门清洗从不同来源拿到的Cookie字符串function cleanCookieString(raw) { return raw .replace(/;\s*Domain[^;]*/gi, ) // 去Domain .replace(/;\s*Path[^;]*/gi, ) // 去Path .replace(/;\s*Expires[^;]*/gi, ) // 去过期时间无意义 .replace(/;\s*Max-Age[^;]*/gi, ) // 去最大存活时间 .replace(/;\s*Secure/gi, ) // 去Secure开发环境用 .replace(/;\s*HttpOnly/gi, ) // 去HttpOnly同上 .replace(/\s/g, ) // 去多余空格 .trim(); }4.2 跨域请求CORS与预检Preflight的特殊处理现在很多前端用Vue/ReactAPI调用走fetch或axios遇到跨域会先发一个OPTIONS预检请求。这个请求没有Body也没有Cookie浏览器策略但FiddlerScript默认也会对它执行OnBeforeRequest。问题来了如果你的脚本里对OPTIONS请求也注入了Cookie而服务端的CORS配置里Access-Control-Allow-Headers没包含Cookie那么预检就会失败后续真正的GET/POST请求根本发不出去。解决方案很简单在OnBeforeRequest的匹配逻辑里显式排除OPTIONS方法if (hostMatch oSession.RequestMethod ! OPTIONS // 关键跳过预检 !oSession.url.toLowerCase().includes(/login) !oSession.url.toLowerCase().includes(/logout)) { // ... 注入逻辑 }这个细节90%的入门教程都不会提但一旦遇到跨域问题你会卡在这里一整天。4.3 FiddlerScript调试如何像调试JavaScript一样调试它FiddlerScript是JScript.NET不是标准JS没有console.log。但Fiddler提供了强大的调试支持日志输出用FiddlerApplication.Log.LogString(message)日志会显示在Fiddler右下角的状态栏也可在Help → Troubleshoot → Logs里查看完整日志文件。断点调试在CustomRules.js里把光标放在某行代码上按F9打上断点。然后在浏览器发一个请求Fiddler会暂停执行你可以用Watch窗口查看oSession对象的所有属性比如oSession.url、oSession.host、oSession.oRequest.headers.Text实时验证你的匹配逻辑是否正确。快速重载改完脚本CtrlS保存Fiddler会自动重新编译脚本无需重启。但如果脚本有语法错误Fiddler会弹窗报错此时状态栏会显示红色Error点开就能看到具体哪一行出错。我习惯在脚本开头加一段调试开关var DEBUG_MODE true; // ... if (DEBUG_MODE) { FiddlerApplication.Log.LogString(DEBUG: Processing oSession.url); }上线前把DEBUG_MODE设为false既不影响性能又能随时打开看日志。4.4 性能与稳定性为什么你的FiddlerScript会变慢理论上FiddlerScript执行是毫秒级的。但如果你的脚本里做了三件事性能就会断崖式下跌频繁读写硬盘比如每次请求都File.ReadAllText读cookie文件。磁盘IO是瓶颈。对策把cookie字符串缓存在内存变量里只在OnBeforeResponse更新时才读写一次。正则滥用比如用oSession.url.match(/.*login.*/i)代替oSession.url.toLowerCase().includes(/login)。正则引擎启动开销远大于字符串查找。大循环遍历比如在OnBeforeRequest里遍历一个1000元素的数组。Fiddler是单线程的卡住主线程所有请求都会排队。优化后的内存缓存版本// 全局变量脚本加载时初始化 var g_cookieStr ; static function OnStart() { try { g_cookieStr System.IO.File.ReadAllText(C:\fiddler_cookies\myapp.txt).Trim(); } catch(e) { g_cookieStr ; } } static function OnBeforeRequest(oSession: Session) { // ... 匹配逻辑 if (hostMatch /* 其他条件 */) { if (g_cookieStr.length 0) { oSession.oRequest.headers.Remove(Cookie); oSession.oRequest.headers.Add(Cookie, g_cookieStr); } } }5. 常见问题速查表从“为什么没生效”到“怎么查日志”最后整理一份我在某图像处理Demo项目、某高校教务系统联调中被同事问得最多的问题清单。每个问题都附带排查路径和终极解决方案帮你5分钟内定位故障。问题现象可能原因排查步骤终极解决方案Fiddler列表里看不到任何HTTPS请求HTTPS解密未开启或证书未安装1. 检查Fiddler Options → HTTPS → “Decrypt HTTPS traffic”是否勾选2. 查看Windows证书管理器 → 受信任的根证书颁发机构 → 是否有“DO_NOT_TRUST_FiddlerRoot”重新勾选HTTPS选项按提示安装证书若已安装但无效删除旧证书重启Fiddler重装注入了Cookie但服务端返回401 UnauthorizedCookie值已过期或域名/Path不匹配1. 在Fiddler里找一个失败的请求 → Inspectors → Headers → Request → 看Cookie字段是否正确2. 对比手动登录时捕获的原始Set-Cookie值用cleanCookieString()函数清洗Cookie确认目标域名白名单是否包含当前请求host浏览器打开空白页或一直转圈代理配置错误或Fiddler未运行1. 在CMD里执行ping 127.0.0.1确认本地回环正常2. 检查Fiddler左上角是否显示“Capturing”3. 浏览器代理设置里地址和端口是否为127.0.0.1:8888关闭Fiddler再重启检查防火墙是否阻止了8888端口临时关闭代理测试是否恢复OnBeforeResponse里更新了cookie但OnBeforeRequest还是用的旧值脚本未重新编译或文件读取缓存1. CtrlS保存CustomRules.js看Fiddler状态栏是否提示“Rules compiled successfully”2. 在OnBeforeRequest里加一行FiddlerApplication.Log.LogString(Current cookie: g_cookieStr);看日志确保OnStart函数里正确读取了新值检查文件路径权限确保Fiddler进程有读写权限注入后页面部分资源图片/CSS加载失败错误地对静态资源请求也注入了Cookie1. 在Fiddler列表里筛选出Result403或500的请求看URL是否为.jpg、.css等2. 检查OnBeforeRequest里的匹配条件是否漏掉了!oSession.url.toLowerCase().includes(.js)等在匹配逻辑里增加排除规则 !oSession.url.toLowerCase().endsWith(.jpg) !oSession.url.toLowerCase().endsWith(.css)最后分享一个小技巧当所有排查都失效时试试“最小化复现”。新建一个最简HTML文件里面只有一行img srchttps://example.com/api/data用配置好代理的浏览器打开。如果这个简单请求能成功说明你的脚本逻辑没问题问题出在复杂页面的某个特定请求上如果它也失败说明是基础环境问题代理、证书、Fiddler配置。这个方法能帮你瞬间把问题域缩小80%。我在某跨平台系统做前后端联调时曾遇到一个诡异问题FiddlerScript对/api/user注入成功但对/api/v2/user就失效。折腾两小时后用最小化复现法发现是v2路径里有个Vary: Accept响应头导致Fiddler缓存了旧响应。解决方案是在OnBeforeRequest里加一行oSession.oRequest.headers[Cache-Control] no-cache;强制不走缓存。这种细节只有在真实战场里才能摸出来。