2017-03-10 151 views
9

我正在編寫一個.NET Core應用程序來輪詢遠程服務器並在數據出現時進行傳輸。這在PHP中是完美的,因爲PHP忽略了證書(這在瀏覽器中也是一個問題),但我們希望將它移到C#.NET CORE中,因爲這是系統中唯一剩餘的PHP。忽略壞證書 - .NET CORE

我們知道服務器很好,但由於種種原因,證書不能很快更新。

的請求正在使用的HttpClient:

 HttpClient httpClient = new HttpClient(); 
     try 
     { 
      string url = "https://URLGoesHere.php"; 
      MyData md = new MyData(); // this is some data we need to pass as a json 
      string postBody = JsonConvert.SerializeObject(md); 
      httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));     
      HttpResponseMessage wcfResponse = await httpClient.PostAsync(url, new StringContent(postBody, Encoding.UTF8, "application/json")); 
      Console.WriteLine(wcfResponse.Content); 
     } 
     catch (HttpRequestException hre) 
     { 
     // This exception is being triggered 
     } 

已經研究這個似乎普遍的建議是使用ServicePointManager,但這不是在.NET中提供的核心,我無法找到建議更換。

有沒有一個簡單的或更好的方法在.NET Core中做到這一點?

+2

這可能是有用的http://stackoverflow.com/questions/2675133/c-sharp-ignore-certificate-errors –

+2

可能重複的[繞過無效SSL證書在.net核心](http://stackoverflow.com/questions/38138952/bypass-invalid-ssl-certificate-in-net-core) – thmshd

+2

感謝所有指向其他線程的指針 - 但在過去曾經訪問過它們,但仍然有問題 - 它們都不會編譯。每次都有一些無法找到的參考。很明顯,我錯過了一些明顯的東西!小片段沒有提供足夠的信息(對我來說),比如還需要包含或引用其他信息。按Ctrl - 。也沒有提出任何合理的建議。 – DaveEP

回答

5

而不是new HttpClient()

var handler = new System.Net.Http.HttpClientHandler(); 
using (var httpClient = new System.Net.Http.HttpClient(handler)) 
{ 
    handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => 
    { 
     // Log it, then use the same answer it would have had if we didn't make a callback. 
     Console.WriteLine(cert); 
     return errors == SslPolicyErrors.None; 
    }; 

    ... 
} 

類似的東西,應該在Windows上工作,並在Linux上,其中的libcurl編譯使用OpenSSL的。與其他curl後端Linux將拋出一個異常。

+2

僅供參考,它在Mac OS上的.NET Core 1.1中也不起作用。異常消息是:'正在使用的libcurl庫(7.51.0)及其SSL後端(「SecureTransport」)不支持自定義處理證書。一個使用OpenSSL構建的libcurl是必需的。)' – Ricky

+0

Ricky,請參閱我的上述答案以獲得一些選項。 –

+0

@bartonjs:感謝您指出我正確的方向,以瞭解如何在macos和可能的某些Linux版本的所有場景中實現這一功能。這非常有幫助。 –

2

獲取Linux和MacOS工作

如果在Linux或MacOS的,你的工作可能會遇到的一個場景,其中HttpClient不會允許你訪問一個自簽名的證書,即使它是您值得信賴的商店。你可能會得到如下:

System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable 
如果要實現(如在對方的回答顯示)的

handler.ServerCertificateCustomValidationCallback = (request, cert, chain, errors) => 
{ 
    // Log it, then use the same answer it would have had if we didn't make a callback. 
    Console.WriteLine(cert); 
    return errors == SslPolicyErrors.None; 
}; 

這是由於libcurl中的不支持適當的回調機上的版本.Net核心需要爲了收集適當的數據來調用ServerCertificateCustomValidationCallback。例如,框架無法創建cert對象或另一個參數。更多信息,請以.Net核心的問題DOTNET核心的GitHub庫提供解決方法的討論中找到:

https://github.com/dotnet/corefx/issues/19709

解決方法(應該僅用於測試或特定的內部應用)如下:

using System; 
using System.Net.Http; 
using System.Runtime.InteropServices; 

namespace netcurl 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var url = "https://localhost:5001/.well-known/openid-configuration"; 
      var handler = new HttpClientHandler(); 
      using (var httpClient = new HttpClient(handler)) 
      { 
       // Only do this for testing and potentially on linux/mac machines 
       if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && IsTestUrl(url)) 
       { 
        handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator; 
       } 

       var output = httpClient.GetStringAsync(url).Result; 

       Console.WriteLine(output); 
      } 
     } 

     static bool IsTestUrl(string url) => url.Contains("localhost"); 
    } 
} 

沒有爲解決這個問題的另一個途徑,那就是使用的libcurl的一個版本,與OpenSSL的支持編譯。適用於MacOS,這裏是如何做到這一點的好教程:

https://spin.atomicobject.com/2017/09/28/net-core-osx-libcurl-openssl/

對於短版,搶與OpenSSL的支持編譯最新的libcurl的副本:

brew install curl --with-openssl 

你可能不要不想強制整個操作系統使用非Apple版本的libcurl,因此您可能需要使用DYLD_LIBRARY_PATH環境變量而不是使用brew來強制將二進制文件鏈接到OS的常規路徑。

export DYLD_LIBRARY_PATH=/usr/local/opt/curl/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH} 

上述命令可用於在終端中運行dotnet時設置適當的環境變量。但這並不適用於GUI應用程序。如果你正在使用Visual Studio for Mac,您可以設置環境變量在項目運行設置:使用IdentityServer4和令牌授權時

Visual Studio for Mac project run settings

第二種方法是必要的我。 .NET Core 2.0授權管道正在使用HttpClient實例調用令牌授權。由於我無權訪問HttpClient或其HttpClientHandler對象,因此我需要強制HttpClient實例使用合適的libcurl版本,以查看我的可信證書的KeyChain系統根目錄。否則,當嘗試使用Authorize(AuthenticationSchemes = IdentityServerAuthenticationDefaults.AuthenticationScheme)]屬性保護webapi端點時,我會得到System.Net.Http.CurlException: Peer certificate cannot be authenticated with given CA certificates environment variable

在尋找解決方法之前,我花了數小時研究此問題。我的整個目標是在使用IdentityServer4爲macOs開發期間使用自簽名證書來保護我的webapi。希望這可以幫助。

+0

非常感謝您的信息。它幫助我朝着正確的方向前進。 我們正在使用.NET標準2。0所以首先我不明白爲什麼我面臨所有這些問題... 我已經嘗試了一切與捲曲和openssl和那些東西,沒有什麼幫助我。 所以我去了一個討厭的黑客(不能讓你的代碼示例既不工作)。 'if(RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) handler.ServerCertificateCustomValidationCallback = null; }' – martinmose