私は.Net Coreで遊んで、支払いAPIを利用するAPIを構築していました。双方向SSL認証の要求に追加する必要があるクライアント証明書があります。 HttpClientを使用して.Net Coreでこれを実現するにはどうすればよいですか?
さまざまな記事を見て、HttpClientHandlerにはクライアント証明書を追加するオプションがないことを発見しました。
お知らせ下さい
同様のプロジェクトがあり、サービス間、およびサービスを使用してモバイルとデスクトップの間で通信します。
EXEからのAuthenticode証明書を使用して、要求を実行しているのがバイナリであることを確認します。
要求側(投稿の簡略化)。
Module m = Assembly.GetEntryAssembly().GetModules()[0];
using (var cert = m.GetSignerCertificate())
using (var cert2 = new X509Certificate2(cert))
{
var _clientHandler = new HttpClientHandler();
_clientHandler.ClientCertificates.Add(cert2);
_clientHandler.ClientCertificateOptions = ClientCertificateOption.Manual;
var myModel = new Dictionary<string, string>
{
{ "property1","value" },
{ "property2","value" },
};
using (var content = new FormUrlEncodedContent(myModel))
using (var _client = new HttpClient(_clientHandler))
using (HttpResponseMessage response = _client.PostAsync($"{url}/{controler}/{action}", content).Result)
{
response.EnsureSuccessStatusCode();
string jsonString = response.Content.ReadAsStringAsync().Result;
var myClass = JsonConvert.DeserializeObject<MyClass>(jsonString);
}
}
次に、リクエストを取得するアクションで次のコードを使用します
X509Certificate2 clientCertInRequest = Request.HttpContext.Connection.ClientCertificate;
if (!clientCertInRequest.Verify() || !AllowedCerialNumbers(clientCertInRequest.SerialNumber))
{
Response.StatusCode = 404;
return null;
}
500よりも404を提供するのは、URLが間違ったリクエストを取得しようとしているので、「正しい軌道に乗っている」ことを知らせるためです。
次の手順に従って、プラットフォーム(Linux Mint 17.3)の新規インストールを実行しました: https://www.Microsoft.com/net/core 。 netcoreapp1.0
フレームワークを対象とした新しいコンソールアプリケーションを作成し、クライアント証明書を送信できました。ただし、有効な証明書を使用していても、テスト中に「SSL接続エラー」(CURLE_SSL_CONNECT_ERROR 35
)を受け取りました。私のエラーは、libcurlに固有のものである可能性があります。
update:Windows 7でまったく同じことを実行し、必要に応じて正確に機能しました。
// using System.Net.Http;
// using System.Security.Authentication;
// using System.Security.Cryptography.X509Certificates;
var handler = new HttpClientHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.SslProtocols = SslProtocols.Tls12;
handler.ClientCertificates.Add(new X509Certificate2("cert.crt"));
var client = new HttpClient(handler);
var result = client.GetAsync("https://apitest.startssl.com").GetAwaiter().GetResult();
クライアントに.Netを使用していませんが、サーバー側では、ASP.Net Core WebサイトをIISの背後に展開し、HTTPS +クライアントにIISを構成することで、IISを介して簡単に構成できます。証明書:
iisクライアント証明書の設定:
次に、コードで簡単に取得できます。
var clientCertificate = await HttpContext.Connection.GetClientCertificateAsync();
if(clientCertificate!=null)
return new ContentResult() { Content = clientCertificate.Subject };
私にとってはうまく機能していますが、.Netのものではなく、curlまたはchromeをクライアントとして使用しています。 HTTPSハンドシェイク中に、クライアントはサーバーから要求を取得し、証明書を提供してサーバーに送信します。
つまり、.Net Coreクライアントを使用している場合、プラットフォーム固有のコードを使用することはできず、OS固有の証明書ストアに自分自身を接続してそれを抽出し、サーバーに送信できなかった場合に意味があります。 .Net 4.5.xに対してコンパイルしている場合、簡単に思えます:
https://pfelix.wordpress.com/2012/12/16/using-httpclient-with-ssltls/
Curlをコンパイルするときのように、Windows証明書ストアに接続できるようにするには、特定のWindowsライブラリに対してコンパイルする必要があります。
HttpClientHandlerクラスの.NET標準参照 を見ると、ClientCertificatesプロパティが存在することがわかりますが、 EditorBrowsableState.Never の使用により非表示。これにより、IntelliSenseは表示されなくなりますが、それを使用するコードでは引き続き機能します。
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get; }
.NET Core 2.0 <と.NET Framework 4.7.1 <の両方に使用できます。
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(new X509Certificate2("cert.crt"));
var client = new HttpClient(handler);