TitaniumClient.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. using Newtonsoft.Json;
  2. using Serilog.Core;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using Titanium.Web.Proxy;
  10. using Titanium.Web.Proxy.EventArguments;
  11. using Titanium.Web.Proxy.Http;
  12. using Titanium.Web.Proxy.Models;
  13. using XYY.Core.Standard.TitaniumWebProxy.Model;
  14. namespace XYY.Core.Standard.TitaniumWebProxy
  15. {
  16. public class TitaniumClient
  17. {
  18. #region 构造
  19. private static Logger _logger;
  20. ProxyServer proxyServer;
  21. ExplicitProxyEndPoint explicitEndPoint;
  22. /// <summary>
  23. /// 不做使用,没有fiddler好用
  24. /// 数据获取过程中需要做较多空值判断与处理
  25. /// </summary>
  26. /// <param name="logger"></param>
  27. [Obsolete("没有fiddler好用")]
  28. public TitaniumClient(Logger logger) {
  29. _logger = logger;
  30. proxyServer = new ProxyServer();
  31. explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, ListenPort, true)
  32. {
  33. // 在所有https请求上使用自颁发的通用证书
  34. // 通过不为每个启用http的域创建证书来优化性能
  35. // 当代理客户端不需要证书信任时非常有用
  36. //GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
  37. };
  38. Startup();
  39. }
  40. #endregion
  41. #region 私有
  42. //监听端口,以及代理端口
  43. private const ushort ListenPort = 8877;
  44. private static List<string> _hosts = new List<string>() { "services.frayun.com", "ws.fedex.com:443" };
  45. /// <summary>
  46. /// 证书的处理
  47. /// </summary>
  48. private void EnsureRootCertificate()
  49. {
  50. proxyServer.CertificateManager.CertificateEngine = Titanium.Web.Proxy.Network.CertificateEngine.DefaultWindows;
  51. proxyServer.CertificateManager.EnsureRootCertificate();
  52. }
  53. /// <summary>
  54. /// 事件处理
  55. /// </summary>
  56. private void AddAttachEventListeners()
  57. {
  58. proxyServer.BeforeRequest += OnRequest;
  59. proxyServer.BeforeResponse += OnResponse;
  60. proxyServer.ServerCertificateValidationCallback += OnCertificateValidation;
  61. proxyServer.ClientCertificateSelectionCallback += OnCertificateSelection;
  62. }
  63. private void CutAttachEventListeners()
  64. {
  65. proxyServer.BeforeRequest -= OnRequest;
  66. proxyServer.BeforeResponse -= OnResponse;
  67. proxyServer.ServerCertificateValidationCallback -= OnCertificateValidation;
  68. proxyServer.ClientCertificateSelectionCallback -= OnCertificateSelection;
  69. }
  70. /// <summary>
  71. /// 命中请求
  72. /// 判断是否需要捕获
  73. /// </summary>
  74. /// <param name="oSession"></param>
  75. /// <returns></returns>
  76. private bool isHitRequestFun(SessionEventArgs e)
  77. {
  78. var isHitRequest = false;
  79. if (_hosts.Any(x => x.Contains(e.HttpClient.Request.Host))) // url
  80. {
  81. isHitRequest = true;
  82. }
  83. return isHitRequest;
  84. }
  85. private async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
  86. {
  87. //await Task.Run(() =>
  88. //{
  89. // string hostname = e.HttpClient.Request.RequestUri.Host;
  90. // if (hostname.Contains("fedex.com"))
  91. // {
  92. // // 排除不想代理的Https地址
  93. // // 对于使用证书固定的客户端很有用
  94. // // for example dropbox.com
  95. // e.DecryptSsl = false;
  96. // }
  97. //});
  98. }
  99. /// <summary>
  100. /// 请求时发送
  101. /// </summary>
  102. /// <param name="sender"></param>
  103. /// <param name="e"></param>
  104. /// <returns></returns>
  105. public async Task OnRequest(object sender, SessionEventArgs e)
  106. {
  107. //var requestHeaders = e.HttpClient.Request.Headers;
  108. //var method = e.HttpClient.Request.Method.ToUpper();
  109. //if (isHitRequestFun(e))//(method == "POST" || method == "PUT" || method == "PATCH")
  110. //{
  111. // //// Get/Set request body bytes
  112. // //byte[] bodyBytes = await e.GetRequestBody();
  113. // //e.SetRequestBody(bodyBytes);
  114. // //// Get/Set request body as string
  115. // //string bodyString = await e.GetRequestBodyAsString();
  116. // //e.SetRequestBodyString(bodyString);
  117. // // store request
  118. // // 这样你就能从响应处理器中找到它
  119. // e.UserData = e.HttpClient.Request;
  120. //}
  121. //// 取消带有自定义HTML内容的请求
  122. //// Filter URL
  123. //if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("google.com"))
  124. //{
  125. // e.Ok("<!DOCTYPE html>" +
  126. // "<html><body><h1>" +
  127. // "Website Blocked" +
  128. // "</h1>" +
  129. // "<p>Blocked by titanium web proxy.</p>" +
  130. // "</body>" +
  131. // "</html>");
  132. //}
  133. //// Redirect example
  134. //if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
  135. //{
  136. // e.Redirect("https://www.paypal.com");
  137. //}
  138. }
  139. /// <summary>
  140. /// 返回数据处理
  141. /// </summary>
  142. /// <param name="sender"></param>
  143. /// <param name="e"></param>
  144. /// <returns></returns>
  145. public async Task OnResponse(object sender, SessionEventArgs e)
  146. {
  147. if (isHitRequestFun(e))
  148. {
  149. logData(e);
  150. }
  151. //// read response headers
  152. //var responseHeaders = e.HttpClient.Response.Headers;
  153. ////if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
  154. //if (e.HttpClient.Request.Method == "GET" || e.HttpClient.Request.Method == "POST")
  155. //{
  156. // if (e.HttpClient.Response.StatusCode == 200)
  157. // {
  158. // if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
  159. // {
  160. // byte[] bodyBytes = await e.GetResponseBody();
  161. // e.SetResponseBody(bodyBytes);
  162. // string body = await e.GetResponseBodyAsString();
  163. // e.SetResponseBodyString(body);
  164. // }
  165. // }
  166. //}
  167. //if (e.UserData != null)
  168. //{
  169. // // 从存储在RequestHandler中的UserData属性的访问请求
  170. // var request = (Request)e.UserData;
  171. //}
  172. }
  173. /// <summary>
  174. /// 允许重写默认的证书验证逻辑
  175. /// </summary>
  176. /// <param name="sender"></param>
  177. /// <param name="e"></param>
  178. /// <returns></returns>
  179. public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
  180. {
  181. // 根据证书错误,设置IsValid为真/假
  182. if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
  183. e.IsValid = true;
  184. return Task.CompletedTask;
  185. }
  186. /// <summary>
  187. /// 允许在相互身份验证期间重写默认客户端证书选择逻辑
  188. /// </summary>
  189. /// <param name="sender"></param>
  190. /// <param name="e"></param>
  191. /// <returns></returns>
  192. public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
  193. {
  194. // set e.clientCertificate to override
  195. return Task.CompletedTask;
  196. }
  197. #endregion
  198. /// <summary>
  199. /// 退出
  200. /// </summary>
  201. public void Quit()
  202. {
  203. CutAttachEventListeners();
  204. proxyServer.Stop();
  205. }
  206. public void Startup()
  207. {
  208. EnsureRootCertificate();
  209. AddAttachEventListeners();
  210. proxyServer.AddEndPoint(explicitEndPoint);
  211. proxyServer.Start();
  212. //设置系统代理
  213. //proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
  214. //proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);
  215. }
  216. #region 数据落地
  217. private static void logData(SessionEventArgs e)
  218. {
  219. TitaniumMessage titaniumMessage = new TitaniumMessage()
  220. {
  221. Methods = e.HttpClient.Request.Method.ToUpper(),
  222. FullUrl = e.HttpClient.Request.Url,
  223. ServerConnectionId = e.ServerConnectionId.ToString(),
  224. ClientConnectionId = e.ClientConnectionId.ToString(),
  225. HostName = e.HttpClient.Request.Host,
  226. RequestHeader = e.HttpClient.Request.HeaderText,
  227. RequestBody = e.HttpClient.Request.BodyString,//需要做空判断,否则报错
  228. ResponseHeader = e.HttpClient.Response.HeaderText,
  229. ResponseBody = e.HttpClient.Response.BodyString,
  230. };
  231. _logger.Warning(JsonConvert.SerializeObject(titaniumMessage));
  232. }
  233. #endregion
  234. }
  235. }