返回列表Mobile Debug 介绍与使用

代理数据展示正文解密之HTTP-API数据解密规范

2019-07-08 13:17
代理

Mobile Debug解密功能默认支持DES/3DES/AES/RSA,如果您调试的接口涉及其他加密算法或者混合算法,那么这边文章可以带您了解Mobile Debug代理数据解密的http-api解密规范。


Mobile Debug代理数据解密的http-api解密原理是什么?


当您点击代理列表数据查看详情时,若您配置了http-api解密规则,Mobile Debug会将当前代理数据详情通过POST请求发送到您填写的URL地址,该URL地址返回的响应正文将显示在原先密文位置;

image.png


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);


正在提交您的问题或建议,请不要关闭页面.

您的问题或建议已提交成功,感谢您一如既往的支持与关注.
关闭弹窗

即将跳转到新的反馈通道,请在博客评论区留言.
立即前往

点击刷新验证码

确认并提交

QQ交流反馈群:323396003