在测接口的过程中,少不了的就是去抓包,一来验证client-server的数据交换是否准确,二来,抓包也是在追查问题时的必要步骤;但是随着接口安全越来越被重视,各种对接口的加密方式,导致通过抓包来查看接口内容变得越来越麻烦,趁着放假研究了一下之前一直知道但又模糊的概念——fiddler plugin。
以下几种场景,对需要抓包的测试同行们极不友好1、接口内容有各种加密,从最简单的base64,到aes,再到rsa。。这直接导致无法从抓到的包中直接查看请求内容;2、一些非明文传输协议,例如protobuf,需要用proto文件生成对应语言的库文件进行转换;3、一些非加密字段,但字段命名含义不明确或参数较多,需要对请求中内容进行翻译后展示;
客户端指向测试服务器,测试服务器打印解释后的明文,通过远程工具查看log文件;
在客户端增加debug log的打印,测试时通过android或ios的开发ide进行查看;
在fiddler中自定义插件进行解密,可直接看到解密结果
先看下效果,选中要翻译的请求,切换到自定义选项卡,即可展示明文,如下图:
主要添加fiddler.exe,目的是引用fiddler提供的库
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace SDKDecryption { public partial class DecryptionViewer : UserControl { public DecryptionViewer() { InitializeComponent(); } private void DecryptionViewer_Load(object sender, EventArgs e) { } private void textBox1_TextChanged(object sender, EventArgs e) { } public void setText(string content) { this.richTextBox1.Text = content; } public void clearText() { this.richTextBox1.Clear(); } } }
using Fiddler; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Standard; using System.Windows.Forms; using System.Text.RegularExpressions; namespace SDKDecryption { //实现fiddler内置接口Inspector2, IRequestInspector2, IBaseInspector2 public sealed class Decryption : Inspector2, IRequestInspector2, IBaseInspector2 { private DecryptionViewer myControl = new DecryptionViewer(); private bool m_bReadOnly; private byte[] m_entityBody; private HTTPRequestHeaders m_Headers; private JSONRequestViewer jsonRequestViewer; public Decryption() { this.jsonRequestViewer = new JSONRequestViewer(); } public void DoDecryption() { String path = this.m_Headers.RequestPath; //可以打印log来调试 FiddlerApplication.Log.LogString("-------------test001"+"body"+this.m_entityBody+"len="+this.m_entityBody.Length); if (this.m_entityBody == null || this.m_entityBody.Length == 0) { this.myControl.clearText(); } else { //可以过滤请求uri包含*时再执行 if (path.Contains("test")) { FiddlerApplication.Log.LogString("-------------test002"); //此种方式才能将byte[]转换成常见的base64编码的字符串 String base64Body =System.Text.Encoding.Default.GetString(this.m_entityBody); //将请求内容base64转码写入文本控件 myControl.setText(testresp); } else { String decodeBody =System.Text.Encoding.Default.GetString(this.m_entityBody); myControl.setText(decodeBody); } } } //初始化fiddler请求body public bool bReadOnly { get { return this.m_bReadOnly; } set { this.m_bReadOnly = value; } } //初始化fiddler请求header public HTTPRequestHeaders headers { get { FiddlerApplication.Log.LogString("headers get function."); return m_Headers; } set { this.m_Headers = value; } } //将处理完成的结果关联到界面控件 public override void AddToTab(TabPage o) { o.Text = "Proto2Json"; o.Controls.Add(this.myControl); o.Controls[0].Dock = DockStyle.Fill; } public void Clear() { this.m_entityBody = null; this.myControl.clearText(); } public override int GetOrder() => 100; } }
1、c#不熟悉,写全套的转换逻辑比较费时;2、proto文件有更新的话,还需要重新修改插件源码并重新打包,替换dll;
此处引入另一个服务B,提供一个protobuf转json的接口,fiddler插件tab页被点击触发时,将二进制请求body以http请求的形式post给服务B,由服务B将转换好的json返回给插件,再有插件写入文本控件中;这个服务B可以是任何你熟悉的语言,这样就完美解决了上述两个问题;当然此方法也可以用于其它需求,可以试fiddler本地插件更新起来更灵活;