有個項目需要調用第三方SDK,而SDK獲取伺服器的已安裝的特殊印表機列表返回給調用方。 但我不想依賴這個SDK,因為這個SDK是使用.NET Framework編寫的,而我的項目是使用.NET Core編寫的,並且想要部署在Docker容器內運行。 於是反編譯了SDK,查看源代碼,看到該SDK調用了 ...
有個項目需要調用第三方SDK,而SDK獲取伺服器的已安裝的特殊印表機列表返回給調用方。
但我不想依賴這個SDK,因為這個SDK是使用.NET Framework編寫的,而我的項目是使用.NET Core編寫的,並且想要部署在Docker容器內運行。
於是反編譯了SDK,查看源代碼,看到該SDK調用了一個URL獲取結果。
而這個URL是本地URL,http://localhost開頭的,此時我才知道這個SDK所對應的軟體在伺服器提供了一個本地的Web服務。
於是我在項目里移除這個SDK,直接調用URL。
但獲取結果失敗了,提示“響應狀態代碼不指示成功: 401 (Unauthorized)。”。而直接瀏覽器訪問這個URL卻成功返回結果。
剛開始一臉懵逼,不知道原來是沒有認證的原因在作梗...
很習慣性的就祭出Fiddler監聽這個URL,在瀏覽器里直接訪問這個URL,在Fiddler卻看到這個URL被請求了3次。
當時沒有在意,直接拿到Request Header,塞到HttpClient的Header里,再次請求,還是報錯。
重新粗略地看Fiddler,這時才留意到重覆請求3次的問題。
我以為是請求內重定向,設置AllowAutoRedirect為true,再次請求,又報錯。
又重新仔細地逐條看Fiddler,第二條在Request Header出現了Authorization: Negotiate xxxxxxxxx。
這才知道用了Authorization認證,於是我根據URL埠查到Windows的埠占用列表,順便找到了該埠占用所對應的PID。
找到PID就找到了進程,從而找到進程所在的文件夾目錄,查看它的config配置文件,從配置描述來看,這個Web服務更準確來講是一個WCF服務。
它使用了security節點:
<security mode="TransportCredentialOnly"> <transport clientCredentialType="Windows"></transport> </security>
我設置UseDefaultCredentials為true,再次請求,成功獲取結果。
這是HttpClient請求本地WCF服務 最終代碼:
private static async void Test() { Random rand = new Random(); var r = rand.Next(10000, 99999); string url = "http://localhost:8080/WebPrintService/GetClientPrinters?rand=" + r; var handler = new HttpClientHandler(); //handler.AllowAutoRedirect = true; //handler.UseDefaultCredentials = true; //handler.PreAuthenticate = true; HttpClient httpClient = new HttpClient(handler); //HttpRequestMessage requestMessage = new HttpRequestMessage(); //requestMessage.RequestUri = new Uri(url); //requestMessage.Method = HttpMethod.Get; //requestMessage.Headers.CacheControl.MaxAge = TimeSpan.Zero; //requestMessage.Headers.Authorization=new AuthenticationHeaderValue(); //requestMessage.Headers.Accept.Clear(); //requestMessage.Headers.Accept.ParseAdd("application/json, text/javascript, */*; q=0.01"); //requestMessage.Headers.AcceptEncoding.Clear(); //requestMessage.Headers.AcceptEncoding.ParseAdd("gzip, deflate"); //requestMessage.Headers.AcceptLanguage.Clear(); //requestMessage.Headers.AcceptLanguage.ParseAdd("zh-CN"); //requestMessage.Headers.UserAgent.Clear(); //requestMessage.Headers.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko"); //requestMessage.Headers.Add("X-Requested-With", "XMLHttpRequest"); //var responseMessage = await httpClient.SendAsync(requestMessage); //var result = await responseMessage.Content.ReadAsStringAsync(); var result = await httpClient.GetStringAsync(url); JsonConvert.DeserializeObject<PrinterInfo>(jsonString); //第二種寫法,.NET Framework自帶,無須為了HttpClient使用NuGet引入Microsoft.Net.Http包 //WebRequest request = WebRequest.Create(url); //request.Method = "GET"; //request.UseDefaultCredentials = true; //WebResponse response = request.GetResponse(); //var stream = response.GetResponseStream(); //using (var streamReader = new StreamReader(stream)) //{ // using (var textReader = new JsonTextReader(streamReader)) // { // var serializer = new JsonSerializer(); // var result = serializer.Deserialize<List<PrinterInfo>>(textReader); // } //} }