WebApi HttpClient pas l'envoi d'un certificat client
Je suis en train de sécuriser mon Reposant WebApi service avec ssl et l'authentification du client à l'aide de certificats client.
Pour tester, j'ai généré un certificat auto-signé et placé dans la machine locale, autorités de certification racine approuvées dossier et j'ai généré un "serveur" et "client" certificats.
Standard https au serveur fonctionne sans problème.
Toutefois, j'ai un peu de code dans le serveur pour valider le certificat, ce n'est jamais appelée lorsque je me connecte à l'aide de mon client de test qui fournit de mon certificat du client et le client de test est retourné un 403 Forbidden état.
Ce imples le serveur est défaillant mon certificat avant qu'il n'atteigne mon code de validation.
Cependant si j'ai le feu au fiddler elle connaît un certificat client est nécessaire et me demande de lui en fournir un de Mes Documents\Fiddler2. Je lui ai donné le même certificat du client-je utiliser dans mon test client et mon serveur fonctionne maintenant et a reçu le certificat du client-je m'attendre!
Cela implique que la WebApi client n'est pas correctement l'envoi du certificat, mon client code ci-dessous est à peu près la même que dans les autres exemples que j'ai trouvé.
static async Task RunAsync()
{
try
{
var handler = new WebRequestHandler();
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
handler.ClientCertificates.Add(GetClientCert());
handler.ServerCertificateValidationCallback += Validate;
handler.UseProxy = false;
using (var client = new HttpClient(handler))
{
client.BaseAddress = new Uri("https://hostname:10001/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
var response = await client.GetAsync("api/system/");
var str = await response.Content.ReadAsStringAsync();
Console.WriteLine(str);
}
} catch(Exception ex)
{
Console.Write(ex.Message);
}
}
Des idées pourquoi il serait de travailler dans un violon, mais pas dans mon test de la client?
Edit: Voici le code à GetClientCert()
private static X509Certificate GetClientCert()
{
X509Store store = null;
try
{
store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadOnly);
var certs = store.Certificates.Find(X509FindType.FindBySubjectName, "Integration Client Certificate", true);
if (certs.Count == 1)
{
var cert = certs[0];
return cert;
}
}
finally
{
if (store != null)
store.Close();
}
return null;
}
Accordé le code de test ne prend pas en charge une valeur null certificat mais je suis débogage pour enssure que le certificat correct est situé.
- Avez-vous vérifié que GetClientCert retourne le certificat que vous attendez?
- Oui 🙂 Ce que le GetClientCert n'est la recherche de la client cert de la localmachine magasin personnel, qui est le même certificat que j'ai donné à fiddler. Cependant, même si c'était une autre cert je m'attends au serveur de validation de code pour obtenir des appelés?
- Dépend de la façon dont le service est hébergé. IIS par exemple ne la validation de certificat, et sera de retour 403, sans jamais appeler votre code.
- Je suis auto-hébergement le service tel qu'il est embeded dans un service windows. Cependant, quels seraient les critères IIS retour 403 pour? je suppose que ce critère serait appliquée à travers le conseil, mais encore une fois le même certificat fonctionne quand Fiddler est impliqué, donc je pense que d'une certaine façon la HttpClient n'est pas l'envoi du certificat correctement.
- À partir de ce lien: stackoverflow.com/questions/19125896/... :
client will only use a client certificate (from the WebRequestHandler.ClientCertificates collection) if it has chain of trust to one of the server's trusted roots
. Je suppose que votre certificat n'est pas approuvé (auto-signé). - Avez-vous jamais trouver un moyen pour HttpClient pour utiliser une non vérification de certificat?
- pourriez-vous partager la solution le cas échéant?
Vous devez vous connecter pour publier un commentaire.
Est votre code ci-dessus s'exécutant dans le même compte d'utilisateur qui Fiddler's exécutant? Si pas, il peut avoir accès au fichier de certificat, mais pas la bonne clé privée. De même, quel est votre
GetClientCert()
de retour de la fonction? Plus précisément, a-t-elle laPrivateKey
bien ensemble?GetClintCert()
méthode renvoie mon attendus certificat de client, leHasPrivateKey
propriété est vraieGetClientCert()
Il y a 2 types de certificats. Le premier est le public .cer fichier qui est envoyé par le propriétaire du serveur. Ce fichier n'est qu'une longue chaîne de caractères. Le second est le fichier de clés de certificat, c'est le autosignés cert-vous de créer et d'envoyer le fichier cer pour le serveur que vous appelez et ils l'installer. En fonction de la sécurité de combien vous avez, vous pourriez avoir besoin d'ajouter un ou deux de ces pour le Client (Handler dans votre cas). Je n'ai vu que le fichier de clés cert utilisé sur un serveur où la sécurité est TRÈS sécurisé. Ce code est à la fois des certificats à partir de la corbeille/déployé dossier:
Aussi - vous avez besoin pour gérer cert erreurs (note: ce qui est MAUVAIS - il est dit que TOUS les cert questions sont d'accord), vous devez modifier ce code pour gérer spécifiques cert problèmes comme la non-concordance de Nom. il est sur ma liste de choses à faire. Il y a beaucoup d'exemple sur la façon de le faire.
Ce code en haut de votre méthode
Méthode quelque part dans votre classe
Dans le code que vous utilisez
store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
.Certificats Client ne sont pas repris à partir de
LocalMachine
, vous devez utiliser à la placeStoreLocation.CurrentUser
.Vérification
MMC -> File -> Add or Remove Snap-ins -> Certificates -> My user account
vous verrez le certificat fiddler utilise. Si vous le retirez deMy user account
et seulement l'avoir importé dansComputer account
vous verrez que Fiddler ne peut pas le prendre soit.Une note de côté, c'est quand la recherche de certificats, vous devez également l'adresse de la culture.
Exemple: