web-dev-qa-db-fra.com

Ajouter un certificat client au noyau .net Httpclient

Je jouais avec .Net Core et construisais une API qui utilisait des API de paiement. Un certificat client doit être ajouté à la demande d'authentification SSL bidirectionnelle. Comment puis-je réaliser cela dans .Net Core en utilisant HttpClient?

J'ai consulté divers articles et constaté que HttpClientHandler ne fournit aucune option pour ajouter des certificats clients.

S'il vous plaît donnez votre avis

27
Krishna.N

J'ai un projet similaire dans lequel je communique entre services, ainsi qu'entre mobile et desktop avec un service. 

Nous utilisons le certificat Authenticode de l’EXE pour nous assurer que ce sont nos fichiers binaires qui exécutent les demandes. 

Du côté du demandeur (trop simplifié pour le poste). 

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

J'utilise ensuite le code suivant sur l'action qui obtient la demande

X509Certificate2 clientCertInRequest = Request.HttpContext.Connection.ClientCertificate;
if (!clientCertInRequest.Verify() || !AllowedCerialNumbers(clientCertInRequest.SerialNumber))
{
    Response.StatusCode = 404;
    return null;
}

Nous préférons fournir un 404 plutôt qu'un 500, car nous aimons ceux qui tentent d'obtenir une mauvaise requête plutôt que de leur faire savoir qu'ils sont sur la bonne voie

J'ai exécuté une nouvelle installation pour ma plate-forme (Linux Mint 17.3) en procédant comme suit: https://www.Microsoft.com/net/core . J'ai créé une nouvelle application console ciblant le framework netcoreapp1.0, capable de soumettre un certificat client. Cependant, j'ai reçu une "erreur de connexion SSL" (CURLE_SSL_CONNECT_ERROR 35) lors des tests, même si j'utilisais un certificat valide. Mon erreur pourrait être spécifique à mon libcurl.

update: J'ai exécuté exactement la même chose sous Windows 7 et cela a fonctionné exactement comme il convient.

// 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();
26
yfisaqt

Je n'utilise pas .Net pour mon client, mais côté serveur, il peut être configuré simplement via IIS en déployant mon site Web Asp.Net Core derrière IIS, en configurant IIS pour les certificats clients HTTPS +:

paramètre de certificat client iis:

Ensuite, vous pouvez l'obtenir simplement dans le code:

        var clientCertificate = await HttpContext.Connection.GetClientCertificateAsync();

        if(clientCertificate!=null)
            return new ContentResult() { Content = clientCertificate.Subject };

Cela fonctionne très bien pour moi, mais j'utilise curl ou chrome en tant que clients et non en .Net. Lors de l'établissement de la liaison HTTPS, le client reçoit une demande du serveur pour fournir un certificat et l'envoyer au serveur. 

Si vous utilisez un client .Net Core, il ne peut pas avoir de code spécifique à la plate-forme et il serait logique de ne pas se connecter à un magasin de certificats spécifique au système d'exploitation, de l'extraire et de l'envoyer au serveur. Si vous compiliez contre .Net 4.5.x, cela semble facile:

https://pfelix.wordpress.com/2012/12/16/using-httpclient-with-ssltls/

C'est comme si vous compiliez curl, si vous voulez pouvoir le connecter au magasin de certificats Windows, vous devez le compiler avec une bibliothèque Windows spécifique.

2
Daboul

Si vous examinez la référence .NET Standard de la classe HttpClientHandler , vous pouvez constater que la propriété ClientCertificates existe, mais est masquée en raison de l'utilisation de EditorBrowsableState.Never . Cela empêche IntelliSense de l'afficher, mais fonctionnera toujours dans le code qui l'utilise.

[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public System.Security.Cryptography.X509Certificates.X509CertificateCollection ClientCertificates { get; }
0
Vivelin