Mobile Debug解密功能默认支持DES/3DES/AES/RSA,如果您调试的接口涉及其他加密算法或者混合算法,那么这边文章可以带您了解Mobile Debug代理数据解密的http-api解密规范。
Mobile Debug代理数据解密的http-api解密原理是什么?
当您点击代理列表数据查看详情时,若您配置了http-api解密规则,Mobile Debug会将当前代理数据详情通过POST请求发送到您填写的URL地址,该URL地址返回的响应正文将显示在原先密文位置;
Mobile Debug解密数据POST了哪些信息?
POST数据提交了1个标准的JSON数据包,包含了以下字段:
{ /**是否是来自解密RequestBody的请求,如果为false则为解密ResponseBody*/ isRequest : false, /**请求正文的原始流数据的base64编码文本(如果有)*/ requestBodyBase64 : null, /**请求正文的字符编码对应的代码页标识符(CodePage),如果不存在请求正文则该值为0*/ requestBodyEncoding : 0, /**请求原始header头*/ requestHeaders : "Host: 192.168.1....", /**请求端的ip地址和端口信息*/ requestIpAddress : "192.168.1.8:51319", /**请求类型 GET POST PUT等*/ requestMethod : "GET", /**请求发起时间对应的格式化字符串*/ requestTime : "/Date(1562566069915+0800)/", /**响应正文的原始流数据的base64编码文本(如果有)*/ responseBodyBase64 : "SGVsbG8gV29ybGQ=", /**响应正文的字符编码对应的代码页标识符(CodePage),如果不存在响应正文则该值为0*/ responseBodyEncoding : 65001, /**响应原始headers*/ responseHeaders : "Cache-Control: private\r\nContent-Type: text/plain", /**响应端的ip地址和端口信息*/ responseIpAddress : "192.168.1.92:80", /**服务端响应状态码*/ responseStatus : "200", /**收到响应时间对应的格式化字符串*/ responseTime : "/Date(1562566069926+0800)/", /**请求URL*/ url : "http://192.168.1.92/test/decode/response-http-api.ashx" }
API接口返回值有何要求?
响应状态码必须为200,正文信息将会展示在Mobile Debug的界面中,如果返回值为标准的JSON,则默认会自动进行解析展示。
为什么是HTTP-API而不走插件?
插件需要将代码部署在Mobile Debug程序中,而HTTP协议是个网络传输协议标准,之所以采取http-api的方式处理解密主要考虑到以下因素:
1.密钥信息的安全性问题;http解密只需由api接口人员编写一套代码部署在内网服务器中,无需将具体代码下发到开发和测试人员,降低了密钥泄露的风险。
2.通用性,http协议是个广泛通用的网络传输协议,这意味着服务端实现无需和Mobile Debug的开发语言保持一致,nodejs,C#,PHP,Java等,降低了开发人员编写解密API的学习成本。
3.独立性;保证了Mobile Debug程序的稳定性。
以下是部分语言读取JSON的demo:
C#
<%@ WebHandler Language="C#" Class="http_api_c_sharp" %> using System; using System.Web; using System.Runtime.Serialization; using System.Runtime.Serialization.Json; using System.IO; using System.Text; public class http_api_c_sharp : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/plain"; var httpMethod = context.Request.HttpMethod; if (httpMethod != "POST") { context.Response.StatusCode = 500; context.Response.Write("不支持的提交方式:" + httpMethod); context.Response.End(); return; } var contentLength = context.Request.ContentLength; if (contentLength < 1) { context.Response.StatusCode = 500; context.Response.Write("请求正文为空"); context.Response.End(); return; } byte[] data = new byte[contentLength]; using (var reader = context.Request.InputStream) { reader.Read(data, 0, contentLength); } var value = context.Request.ContentEncoding.GetString(data); var proxyData = JSON.parse<MobileDebugProxyData>(value); context.Response.Write(JSON.stringify(proxyData)); } public bool IsReusable { get { return false; } } /// <summary> /// Mobile Debug代理数据信息 /// </summary> [DataContract(Namespace = "http://www.mobiledebug.com/")] public class MobileDebugProxyData { /// <summary> /// 是否是来自解密RequestBody的请求,如果为false则为解密ResponseBody /// </summary> /// <returns></returns> [DataMember(Name = "isRequest")] public bool IsRequest { get; set; } /// <summary> /// 请求URL /// </summary> /// <returns></returns> [DataMember(Name = "url")] public string Url { get; set; } /// <summary> /// 请求类型 GET POST PUT等 /// </summary> /// <returns></returns> [DataMember(Name = "requestMethod")] public string RequestMethod { get; set; } /// <summary> /// 请求原始header头 /// </summary> /// <returns></returns> [DataMember(Name = "requestHeaders")] public string RequestHeaders { get; set; } /// <summary> /// 请求正文的字符编码对应的代码页标识符(CodePage),如果不存在请求正文则该值为0 /// </summary> /// <returns></returns> [DataMember(Name = "requestBodyEncoding")] public int RequestBodyEncoding { get; set; } /// <summary> /// 请求正文的原始流数据的base64编码文本(如果有) /// </summary> /// <returns></returns> [DataMember(Name = "requestBodyBase64")] public string RequestBodyBase64 { get; set; } /// <summary> /// 请求发起时间 /// </summary> /// <returns></returns> [DataMember(Name = "requestTime")] public DateTime RequestTime { get; set; } /// <summary> /// 请求端IP地址和端口号 /// </summary> /// <returns></returns> [DataMember(Name = "requestIpAddress")] public string RequestIpAddress { get; set; } /// <summary> /// 响应状态码 /// </summary> /// <returns></returns> [DataMember(Name = "responseStatus")] public string ResponseStatus { get; set; } /// <summary> /// 响应headers /// </summary> /// <returns></returns> [DataMember(Name = "responseHeaders")] public string ResponseHeaders { get; set; } /// <summary> /// 请求正文的流数据的base64编码文本(如果有) /// </summary> /// <returns></returns> [DataMember(Name = "responseBodyBase64")] public string ResponseBodyBase64 { get; set; } /// <summary> /// 响应正文的字符编码对应的代码页标识符(CodePage),如果不存在响应正文则该值为0 /// </summary> /// <returns></returns> [DataMember(Name = "responseBodyEncoding")] public int ResponseBodyEncoding { get; set; } /// <summary> /// 响应返回时间 /// </summary> /// <returns></returns> [DataMember(Name = "responseTime")] public DateTime ResponseTime { get; set; } /// <summary> /// 响应端IP地址和端口号 /// </summary> /// <returns></returns> [DataMember(Name = "responseIpAddress")] public string ResponseIpAddress { get; set; } } /// <summary> /// 解析JSON /// </summary> public static class JSON { /// <summary> /// 将字符串序列化为指定的对象 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="jsonString"></param> /// <returns></returns> /// <remarks></remarks> public static T parse<T>(string jsonString) { if (string.IsNullOrEmpty(jsonString)) return default(T); try { using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString))){ var type1 = typeof(T); var data = new DataContractJsonSerializer(type1); var obj = (T)data.ReadObject(ms); return obj; } } catch { return default(T); } } /// <summary> /// 将对象序列化成字符串 /// </summary> /// <param name="jsonObject"></param> /// <returns></returns> /// <remarks></remarks> public static string stringify(Object jsonObject ) { try { using (var ms = new MemoryStream()) { var d = new DataContractJsonSerializer(jsonObject.GetType()); d.WriteObject(ms, jsonObject); return Encoding.UTF8.GetString(ms.ToArray()); }} catch { return null; } } } }
VB.NET
<%@ WebHandler Language="VB" Class="http_api" %> Imports System Imports System.Web Imports System.Runtime.Serialization Imports System.Runtime.Serialization.Json Imports System.IO Imports System.Text Public Class http_api : Implements IHttpHandler Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest context.Response.ContentType = "text/plain" Dim httpMethod = context.Request.HttpMethod If httpMethod <> "POST" Then context.Response.StatusCode = 500 context.Response.Write("不支持的提交方式:" & httpMethod) context.Response.End() Return End If Dim contentLength = context.Request.ContentLength If contentLength < 1 Then context.Response.StatusCode = 500 context.Response.Write("请求正文为空") context.Response.End() Return End If Dim data = New Byte(contentLength - 1) {} Using reader = context.Request.InputStream reader.Read(data, 0, contentLength) End Using Dim value = context.Request.ContentEncoding.GetString(data) Dim proxyData = JSON.parse(Of MobileDebugProxyData)(value) context.Response.Write(JSON.stringify(proxyData)) End Sub Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property ''' <summary> ''' Mobile Debug代理数据信息 ''' </summary> <DataContract(Namespace:="http://www.mobiledebug.com/")> Public Class MobileDebugProxyData ''' <summary> ''' 是否是来自解密RequestBody的请求,如果为false则为解密ResponseBody ''' </summary> ''' <returns></returns> <DataMember(Name:="isRequest")> Public Property IsRequest As Boolean ''' <summary> ''' 请求URL ''' </summary> ''' <returns></returns> <DataMember(Name:="url")> Public Property Url As String ''' <summary> ''' 请求类型 GET POST PUT等 ''' </summary> ''' <returns></returns> <DataMember(Name:="requestMethod")> Public Property RequestMethod As String ''' <summary> ''' 请求原始header头 ''' </summary> ''' <returns></returns> <DataMember(Name:="requestHeaders")> Public Property RequestHeaders As String ''' <summary> ''' 请求正文的字符编码对应的代码页标识符(CodePage),如果不存在请求正文则该值为0 ''' </summary> ''' <returns></returns> <DataMember(Name:="requestBodyEncoding")> Public Property RequestBodyEncoding As Integer ''' <summary> ''' 请求正文的原始流数据的base64编码文本(如果有) ''' </summary> ''' <returns></returns> <DataMember(Name:="requestBodyBase64")> Public Property RequestBodyBase64 As String ''' <summary> ''' 请求发起时间 ''' </summary> ''' <returns></returns> <DataMember(Name:="requestTime")> Public Property RequestTime As DateTime ''' <summary> ''' 请求端IP地址和端口号 ''' </summary> ''' <returns></returns> <DataMember(Name:="requestIpAddress")> Public Property RequestIpAddress As String ''' <summary> ''' 响应状态码 ''' </summary> ''' <returns></returns> <DataMember(Name:="responseStatus")> Public Property ResponseStatus As String ''' <summary> ''' 响应headers ''' </summary> ''' <returns></returns> <DataMember(Name:="responseHeaders")> Public Property ResponseHeaders As String ''' <summary> ''' 请求正文的流数据的base64编码文本(如果有) ''' </summary> ''' <returns></returns> <DataMember(Name:="responseBodyBase64")> Public Property ResponseBodyBase64 As String ''' <summary> ''' 响应正文的字符编码对应的代码页标识符(CodePage),如果不存在响应正文则该值为0 ''' </summary> ''' <returns></returns> <DataMember(Name:="responseBodyEncoding")> Public Property ResponseBodyEncoding As Integer ''' <summary> ''' 响应返回时间 ''' </summary> ''' <returns></returns> <DataMember(Name:="responseTime")> Public Property ResponseTime As DateTime ''' <summary> ''' 响应端IP地址和端口号 ''' </summary> ''' <returns></returns> <DataMember(Name:="responseIpAddress")> Public Property ResponseIpAddress As String End Class ''' <summary> ''' 解析JSON ''' </summary> Public Class JSON Private Sub New() End Sub ''' <summary> ''' 将字符串序列化为指定的对象 ''' </summary> ''' <typeparam name="T"></typeparam> ''' <param name="jsonString"></param> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function parse(Of T)(jsonString As String) As T If String.IsNullOrEmpty(jsonString) Then Return Nothing End If Try Using ms = New MemoryStream(Encoding.UTF8.GetBytes(jsonString)) Dim type1 = GetType(T) Dim data = New DataContractJsonSerializer(type1) Dim obj As T = data.ReadObject(ms) Return obj End Using Catch Return Nothing End Try End Function ''' <summary> ''' 将对象序列化成字符串 ''' </summary> ''' <param name="jsonObject"></param> ''' <returns></returns> ''' <remarks></remarks> Public Shared Function stringify(jsonObject As Object) As String Try Using ms = New MemoryStream() Dim d = New DataContractJsonSerializer(jsonObject.GetType()) d.WriteObject(ms, jsonObject) Return Encoding.UTF8.GetString(ms.ToArray()) End Using Catch Return Nothing End Try End Function End Class End Class
NodeJS (node server.js)
//server.js var http = require("http"); http.createServer((req,res)=>{ res.writeHead(200,{'Content-Type':'text/plain;charset=utf-8'}); if(req.method!=="POST"){ res.write("不支持的Method:"+req.method); res.end(); return; } req.on("data",(chunk)=>{ let data=chunk.toString(); try{ proxyData = JSON.parse(data); }catch(ex){ proxyData=null; } if(proxyData===null){ res.write("数据接收异常"); res.end(); return; } res.write("客户端提交的信息为:" + JSON.stringify(proxyData)); res.end(); }); }).listen(8920);