FiddlerCoreAPI开发(一)源码分析

1.前言

前一段时间想利用fiddlercore截取本地HTTPS的流量做一些分析,按照样例代码的注释学习了一下,没搞清楚怎么实现,后来又在网上查了些资料,对HTTPS的处理提及很少,都没有解决我的问题,主要是HTTPS证书的问题,索性自己研究了一下,终于解决了问题。我会在下篇文章中分享下我的思路,本篇文章先简单分析下fiddlercore自带样例的代码,帮助刚接触fiddlercore的人快速入门,如果有说的不对的地方,欢迎批评指正。

2.源码分析

首先从官网下载FiddlerCoreAPI
https://www.telerik.com/purchase/fiddlercore

下载下来是一个安装文件,解压后有demo和FiddlerCoreAPI库,打开样例代码工程,开始分析。

从主函数开始。

List<Fiddler.Session> oAllSessions = new List<Fiddler.Session>();

定义了一个fiddler的Session类的List,里面存放的是客户端和服务端的消息。

Fiddler.FiddlerApplication.SetAppDisplayName("FiddlerCoreDemoApp");

命名自己的应用程序。

Fiddler.FiddlerApplication.OnNotification += delegate(object sender, NotificationEventArgs oNEA) { Console.WriteLine("** NotifyUser: " + oNEA.NotifyString); };
Fiddler.FiddlerApplication.Log.OnLogString += delegate(object sender, LogEventArgs oLEA) { Console.WriteLine("** LogString: " + oLEA.LogString); };

这两句,第一句绑定了用户通知事件的函数,具体什么时候触发没仔细研究,第二句绑定了FiddlerApplication.Log触发的事件(FiddlerCore自己的日志系统),后面打印内容都会用到,总之这两句就是把内容打印在控制台上。

Fiddler.FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oS)
{
// Console.WriteLine("Before request for:\t" + oS.fullUrl);
oS.bBufferResponse = false;
Monitor.Enter(oAllSessions);
oAllSessions.Add(oS);
Monitor.Exit(oAllSessions);

if ((oS.oRequest.pipeClient.LocalPort == iSecureEndpointPort) && (oS.hostname == sSecureEndpointHostname))
{
oS.utilCreateResponseAndBypassServer();
oS.oResponse.headers.SetStatus(200, "Ok");
oS.oResponse["Content-Type"] = "text/html; charset=UTF-8";
oS.oResponse["Cache-Control"] = "private, max-age=0";
oS.utilSetResponseBody("Request for httpS://" + sSecureEndpointHostname + ":" + iSecureEndpointPort.ToString() + " received. Your request was:

&amp;quot; + oS.oRequest.headers.ToString());&lt;br&gt; }&lt;br&gt; };&lt;/p&gt; &lt;p&gt;BeforeRequest,顾名思义,就是在客户端发送请求后拦截之,在此函数中可以获取甚至修改请求的内容。&lt;/p&gt; &lt;p&gt;oS.fullUrl为请求的URL。&lt;/p&gt; &lt;p&gt;bBufferResponse这个属性,要设置成true才可以修改服务器响应的内容。&lt;/p&gt; &lt;p&gt;接下来的if判断,是一个例子,如果你访问 &lt;a href="https://localhost:7777" target="_blank"&gt;https://localhost:7777&lt;/a&gt; ,他会拦截你的请求,并构造响应报文返回给你,服务端不会收到该请求。&lt;/p&gt; &lt;p&gt;Fiddler.FiddlerApplication.Startup(iPort, oFCSF);&lt;/p&gt; &lt;p&gt;开启FiddlerCore在指定端口的监听。&lt;/p&gt; &lt;p&gt;oSecureEndpoint = FiddlerApplication.CreateProxyEndpoint(iSecureEndpointPort, true, sSecureEndpointHostname);&lt;/p&gt; &lt;p&gt;建立在指定端口的HTTPS的监听,这个函数下篇文章中还会说到。&lt;/p&gt; &lt;p&gt;至此,这个样例的主要代码就分析完了,它实现了简单的http请求截获和响应替换,剩余的代码都是些与用户的交互,这里不再赘述。&lt;/p&gt; &lt;h2 id="3注意"&gt;3.注意&lt;/h2&gt; &lt;p&gt;前面代码执行完后,一定要调用Shutdown()函数关闭FiddlerCore应用,不然会导致浏览器还是通过Fiddler代理,上不了网。&lt;/p&gt; &lt;p&gt;Fiddler.FiddlerApplication.Shutdown();&lt;/p&gt; &lt;p&gt;在证书管理器中可以看到FiddlerCore安装了自己的证书。&lt;/p&gt; &lt;p&gt;&lt;img src="http://images2017.cnblogs.com/blog/1209573/201712/1209573-20171220202829131-1078374781.png" alt="" loading="lazy"&gt;&lt;/p&gt; &lt;p&gt;阅读样例代码的注释很有帮助,还有FiddlerCore的&lt;a href="http://download.csdn.net/download/u010156775/10164938" target="_blank"&gt;帮助文档&lt;/a&gt;,里面各个函数的功能说的很详细。&lt;/p&gt; </plaintext> </div> <div class="clear"></div> <div id="blog_post_info_block" role="contentinfo" class="post-meta-container"> <div id="blog_post_info"></div> <div class="clear"></div> <div id="post_next_prev"></div> </div> </div> <div class="postDesc">posted @ <span id="post-date" data-last-update-days="0.001388888888888889" data-date-updated="2017-12-20 20:34">2017-12-20 20:32</span>&nbsp; <a href="https://www.cnblogs.com/realwy">real王一</a>&nbsp; 阅读(<span id="post_view_count">9451</span>)&nbsp; 评论(<span id="post_comment_count">4</span>)&nbsp; &nbsp; <a href="javascript:void(0)" onclick="AddToWz(8075705);return false;">收藏</a>&nbsp; <a href="https://report.cnblogs.com?targetLink=https%3A%2F%2Fwww.cnblogs.com%2Frealwy%2Fp%2F8075705.html&targetId=8075705&targetType=0" target="_blank">举报</a> </div> </div> </div><!--end: topics 文章、评论容器--> </div> <script> var cb_entryId = 8075705, cb_entryCreatedDate = '2017-12-20 20:32', cb_postType = 1, cb_postTitle = 'FiddlerCoreAPI开发(一)源码分析'; var allowComments = true, cb_blogId = 401053, cb_blogApp = 'realwy', cb_blogUserGuid = '95feb9c7-7dfd-467d-4ac6-08d49c352df3'; mermaidRender.render() markdown_highlight() zoomManager.apply("#cnblogs_post_body img:not(.code_img_closed):not(.code_img_opened)"); </script> <a id="!comments"></a> <div id="blog-comments-placeholder"></div> <div id="comment_form" class="commentform"> <a name="commentform"></a> <div id="divCommentShow"></div> <div id="comment_nav"> <div class="comment-nav-right"> <span id="span_refresh_tips"></span><a href="#" onclick="return RefreshPage();">刷新页面</a><a href="#top">返回顶部</a> </div> </div> <div id="comment_form_container"></div> <div class="ad_text_commentbox" id="ad_text_under_commentbox"></div> <div id="cnblogs_ch"></div> <div id="opt_under_post"></div> <div id="blog_c1" class="under-post-card below-post-card"> <a href="https://harmonyos.cnblogs.com/p/31505" rel="nofollow" target="_blank" onclick="countCreativeClicks('C1-HarmonyOS')"> <img src="https://img2024.cnblogs.com/blog/35695/202608/35695-20260813112442146-282986984.webp" onload="countCreativeImpressions('C1-HarmonyOS')" alt="" style="width:300px!important;height:250px!important;min-width:300px!important;max-width:300px!important;" /> <span id="c1_impression" style="display:none"></span> </a> </div> <div id="under_post_card1"></div> <div id="related_posts_card"></div> <div id="under_post_card2"></div> <div id="HistoryToday" class="under-post-card below-post-card"></div> <script type="text/javascript"> var commentManager = new blogCommentManager(); commentManager.renderComments(0); fixPostBody(); window.footnoteTipManager.generateFootnoteTips(); window.tocManager.displayDisableTocTips = false; window.tocManager.generateToc(); setTimeout(function() { countViews(cb_blogId, cb_entryId); }, 50); deliverT2(); deliverC1C2(); loadNewsAndKb(); LoadPostCategoriesTags(cb_blogId, cb_entryId); LoadPostInfoBlock(cb_blogId, cb_entryId, cb_blogApp, cb_blogUserGuid); GetPrevNextPost(cb_entryId, cb_blogId, cb_entryCreatedDate, cb_postType); loadOptUnderPost(); GetHistoryToday(cb_blogId, cb_blogApp, cb_entryCreatedDate); </script> </div> </div> </div> <div id="sideBar"> <div id="sideBarMain"> <div id="sidebar_news" class="newsItem"> <h3 class="catListTitle">公告</h3> <div id="blog-news" class="sidebar-news"> <div id="sidebar_news_container"> </div> </div> <script>loadBlogNews();</script> </div> <div id="blog-calendar" style="display:none"></div><script>loadBlogDefaultCalendar();</script> <div id="leftcontentcontainer"> <div id="blog-sidecolumn"></div> <script>loadBlogSideColumn()</script> </div> </div> </div> <div class="clear"></div> </div> <div class="clear"></div> <div id="footer"> <a href="https://www.cnblogs.com/" id="footer_site_link" class="footer-brand">博客园</a> <span class="footer-copyright"> &nbsp;&copy;&nbsp; 2004-2026</span> <br /><span class="footer-icp"> <a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=33010602011771"><img src="//assets.cnblogs.com/images/ghs.png" />浙公网安备 33010602011771号</a> <a href="https://beian.miit.gov.cn" target="_blank">浙ICP备2021040463号-3</a> </span> </div> </div> <input type="hidden" id="antiforgery_token" value="CfDJ8Ow5-In01nBEvFwaadRGjqFho9fQj6DDXz1qPEhQJTtVLEltcTYjkBQHjIGknEZ9RniPBuqUlMWc933GLb-pVI8dTCBbYtOFQXS0TJA08mHcYOvzdziHwKwEOuDDoSHPF2VtiResHJBHDD-DXSoW8Kg" /> <script defer src="https://hm.baidu.com/hm.js?866c9be12d4a814454792b1fd0fed295"></script> </body> </html>