Problème de Certificat SSL C#
Dans mon application en C#, j'ai eu à appeler des services web via https et valider à l'aide de un .crt fichier que j'ai déjà. Ici est la bonne solution pour de tels besoins. J'ai mis à jour ce post une fois que j'ai une solution qui fonctionne, en pensant qu'il pourrait aider d'autres personnes comme moi.
SOLUTION :
Le code ci-dessous doit être exécutée qu'une seule fois dans l'ensemble de l'exécution de l'application. Avec cela nous avons mis l'ServerCertification et SSL propriétés qui seront utilisées à chaque fois qu'une demande sera appelé :
public static void setSSLCertificate()
{
clientCert = new X509Certificate2(AUTHEN_CERT_FILE); //Pointing to the .crt file that will be used for server certificate verification by the client
System.Net.ServicePointManager.ServerCertificateValidationCallback += new System.Net.Security.RemoteCertificateValidationCallback(customXertificateValidation);
}
public static bool customXertificateValidation(Object sender, X509Certificate certificate, X509Chain chain, System.Net.Security.SslPolicyErrors sslPoicyErrors)
{
switch (sslPoicyErrors)
{
case System.Net.Security.SslPolicyErrors.RemoteCertificateChainErrors:
case System.Net.Security.SslPolicyErrors.RemoteCertificateNameMismatch:
case System.Net.Security.SslPolicyErrors.RemoteCertificateNotAvailable:
break;
}
return clientCert.Verify(); //Perform the Verification and sends the result
}
Une demande est effectuée normalement, comme nous le faire sans l'implémentation de SSL. Voici un Post de demande de code :
private static String SendPost(String uri, String post_data)
{
String resData = "";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = false;
request.ProtocolVersion = HttpVersion.Version10;
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
//turn request string into byte[]
byte[] postBytes = Encoding.ASCII.GetBytes(post_data);
Stream requestStream = null;
try
{
//Send it
request.ContentLength = postBytes.Length;
requestStream = request.GetRequestStream();
requestStream.Write(postBytes, 0, postBytes.Length);
}
catch (WebException we)
{ //If SSL throws exception that will be handled here
if (we.Status == WebExceptionStatus.TrustFailure)
throw new Exception("Exception Sending Data POST : Fail to verify server " + we.Message);
}
catch (Exception e)
{
throw new Exception("Exception Sending Data POST : " + e.Message, e.InnerException);
}
finally
{
if (requestStream != null)
requestStream.Close();
}
//Get the response
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
if (response == null)
return "";
StreamReader sr = new StreamReader(response.GetResponseStream());
resData = sr.ReadToEnd().Trim();
sr.Close();
}
catch (Exception e)
{
throw new Exception("Error receiving response from POST : " + e.Message, e.InnerException);
}
finally
{
if (response != null)
response.Close();
}
return resData;
}
Un Merci spécial à Dipti Mehta dont explination m'a aidé à atteindre l'objectif en grande partie par accepter le certificat du serveur. Elle m'a aidé à résoudre mon confussions. J'ai enfin trouvé comment faire pour vérifier le certificat du serveur à l'aide .crt fichier par le client.
Espère que cela aide quelqu'un.
Grâce
OriginalL'auteur Tvd | 2011-04-19
Vous devez vous connecter pour publier un commentaire.
Lorsque vous accédez à un site en HTTPS, vous avez probablement une fenêtre de dialogue vous demandant si vous souhaitez faire confiance au certificat fourni par le serveur web. De sorte que la responsabilité d'accepter le certificat est manipulé par l'utilisateur. Revenons à la webservice scénario, si vous souhaitez appeler un webservice situé sur un serveur web qui utilise le protocole SSL et HTTPS il y a un problème.
Lorsque vous effectuez un appel à partir du code, il n'y a pas de fenêtre de dialogue qui s'affichent, et vous demandant si vous faites confiance au certificat ; probablement vous aurez exception suivante:
Mais il y a une solution pour ce problème, vous pouvez résoudre ce problème dans votre code en créant votre propre CertificatePolicy (de la classe qui implémente l'
ICertificatePolicy
interface). Dans ce cours, vous devez écrire votre propre CheckValidationResult fonction doit retourner true ou false, comme vous le feriez appuyez sur oui ou sur non dans la boîte de dialogue de la fenêtre. À des fins de développement, j'ai créé la classe suivante qui accepte tous les certificats, donc vous n'aurez pas la désagréable WebException:Comme vous pouvez le voir le CheckValidationResult fonction renvoie toujours true, de sorte que tous les certificats de confiance. Si vous voulez faire de cette classe un peu plus sécurisé, vous pouvez ajouter des contrôles supplémentaires à l'aide de la X509Certificate paramètre par exemple. Pour utiliser cette CertificatePolicy, vous aurez à dire à la ServicePointManager pour l'utiliser:
Cela doit être fait (une fois pendant le cycle de vie des applications) avant de faire l'appel à votre webservice.
Merci pour ce parfait et droit frward explication. Ok, donc, avec cela, si je veux utiliser mon .crt fichier, j'ai perfomr de validation à l'intérieur de CheckValidationResult contre cert reçue du serveur. Claire jusqu'à présent. Alors qu'est-ce que l'utilisation de la demande.ClientCertificates de la propriété. - Je l'ajouter ou de ne pas l'ajouter, n'est-ce pas faire de differnce après l'ajout de ServicePointManager. Aussi, j'ai ajouté ce code dans SendPost() qui est appelée à chaque fois que je demande pour un service web. Je suis arrivé à supprimer qu'à partir de SendPost() et de le laisser qu'une seule fois. Pouvez-vous aider avec ClientCertificates. Merci
Oui, ce qui doit être fait qu'une seule fois. Le ServicePointManager valide tous les types de certificats. Mais, si vous voulez uniquement de valider certains certificats, vous pouvez spécifier que trop, et dans ce cas, la demande.ClientCertificates sera utile
J'aimerais vérifier avec un certificat (.crt) que j'ai. Dans CheckValidationResult, ont utilisé votre code, & ajouté .ClientCertificates.Ajouter(x509cert2Obj). Mais il ne fait pas la validation par le passé cert. - Je ajouter/supprimer la ligne ci-dessus ne fait aucune différence, je peux accéder au service web. J'ai essayé de créer X509Certificate2 objet à l'aide de nouvelles (string filename) et .D'importation(nom de fichier). Mais aucun ne fonctionne. il n'a pas de différence dans la réponse. COMME je comprends la forme de votre post ci-dessus, après l'ajout de CertificatePolicy, si je veux validae certian cert, j'ai pu ajouter en ClientCertificates. Où vais-je tort
dernier code ajouté au-dessus. Jetez un coup d'oeil.
OriginalL'auteur Dipti Mehta
Salut Tvd,
Je ne suis pas sûr que la solution que vous fournissez est effectivement une solution valide pour le problème. Aussi, certains de vos commentaires au sujet de
HttpWebRequest.ClientCertificates
l'indiquer.Tout d'abord, il est important de faire la distinction entre le serveur de la validation d'un certificat du client et le client de la validation d'un certificat de serveur. Collection
HttpWebRequest.ClientCertificates
est utilisé pour envoyer des certificats client au serveur, le serveur peut valider qui est le client. Votre question (comme je le comprends) était comment certificat de serveur qui ne passe pas la validation par défaut (comme une auto-signé cert) peuvent être validés à l'encontre d'un certificat stocké localement sur le client.Dans ce cas, une solution est en effet d'utiliser
System.Net.ServicePointManager.ServerCertificateValidationCallback
et de fournir une validation personnalisée. Cependant, votre méthode de validation semble erroné: il vérifie le certificat local et ne se soucie pas du cert envoyer par le serveur. Ce que j'avais utiliser est quelque chose comme ceci:Cette méthode garantit que si le certificat du serveur passe la validation par défaut (pas d'erreurs), il va l'accepter et puis il compare les locaux, le client copie du certificat avec ce qui a été fourni par le serveur. Seulement, si est Égal à test passe, le client peut procéder en toute sécurité.
OriginalL'auteur Jacek
Par "valider", vous voulez dire authentifier? Dans ce cas, une .le crt n'est pas assez, il ne contient qu'une clé publique. Vous avez besoin de la clé privée pour vous authentifier et placez-la dans ClientCertificates. Vous pouvez lire un de un .fichier pfx ou de l'importer dans un certificat de conteneur et de l'utiliser à partir de là.
OriginalL'auteur fejesjoco