J'essaie de créer un service Web sécurisé.
Voici le contrat et la mise en œuvre du service
[ServiceContract()]
public interface ICalculatorService
{
[OperationContract()]
int Add(int x, int y);
}
[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public class CalculatorService : ICalculatorService
{
public int Add(int x, int y)
{
return x + y;
}
}
Ici, j'ai le code de service
var b = new WSHttpBinding(SecurityMode.Transport);
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
Type contractType = typeof(ICalculatorService);
Type implementedContract = typeof(CalculatorService);
Uri baseAddress = new Uri("https://localhost:8006/CalculatorService");
ServiceHost sh = new ServiceHost(implementedContract);
sh.AddServiceEndpoint(contractType, b, baseAddress);
//ServiceMetadataBehavior sm = new ServiceMetadataBehavior();
//sm.HttpsGetEnabled = true;
//sm.HttpsGetUrl = new Uri("https://localhost:8006/CalculatorServiceMex");
//sh.Description.Behaviors.Add(sm);
sh.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
sh.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
sh.Open();
Console.WriteLine("Service is Listening");
Console.ReadLine();
sh.Close();
Voici le code client
var b = new WSHttpBinding(SecurityMode.Transport);
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
b.Security.Message.ClientCredentialType = MessageCredentialType.None;
var factory = new ChannelFactory<ICalculatorService>(b);
factory.Credentials.Peer.PeerAuthentication.CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.PeerTrust;
factory.Credentials.ClientCertificate.SetCertificate(StoreLocation.LocalMachine, StoreName.TrustedPeople, X509FindType.FindBySubjectName, "localhost");
var client = factory.CreateChannel(new EndpointAddress(new Uri("https://localhost:8006/CalculatorService")));
ServicePointManager.ServerCertificateValidationCallback =
((sender, certificate, chain, sslPolicyErrors) =>
{
return true;
});
ICommunicationObject comObject = client as ICommunicationObject;
int result = -1;
try
{
comObject.Open();
result = client.Add(10, 2);
}
catch (Exception ex)
{
}
Console.WriteLine(string.Format("Service say 10 + 2 = {0}", -1));
Console.ReadLine();
Le service s'exécute correctement et lorsque la vérification ServicePointManager.ServerCertificateValidationCallback est effectuée, il n'y a aucune erreur de stratégie, avec la chaîne de certificats correcte créée.
J'ai mon CA dans la racine approuvée et le certificat serveur/client dans le magasin TrustedPeople. Aussi, si je navigue sur le site à partir d'un navigateur, je vois une page renvoyée. Aucune erreur
J'ai mis à jour IIS à ce que je pense être le nécessaire, lié le certificat dans IIS
et via la ligne de commande ci-dessous.
J'ai défini les paramètres SSL pour accepter les certificats
et activé l'authentification anonyme.
Quelqu'un sait-il quelles étapes je n'ai pas faites correctement ou voit-il quelque chose de mal? Je reçois toujours la même erreur "La requête HTTP a été interdite avec le schéma d'authentification client 'Anonymous'."
Une autre raison à cela est le certificat lui-même sur le serveur que vous rencontrez. Assurez-vous d'avoir importé la CLÉ PRIVÉE. Dans MMC cela apparaîtra avec un "nom convivial". Cela m'a pris des jours à comprendre. Une fois que j'ai importé la clé privée, l'erreur anonyme a disparu et tout s'est bien passé!
Lorsque vous hébergez le service WCF dans IIS avec transport de type de sécurité et certificat de type d'informations d'identification client, placez votre certificat client sur le magasin racine et activez l'authentification anonyme dans IIS . Activez l'authentification anonyme dans IIS. Mais surtout, ajoutez votre certificat au magasin racine.
Si vous exécutez le service WCF auto-hébergé (sans IIS), vous pouvez activer les clients anonymes en ajoutant au fichier de configuration (sur le serveur) les éléments suivants:
<behaviors>
<serviceBehaviors>
<behavior name="limitedAuthBehavior">
<serviceAuthenticationManager authenticationSchemes="Anonymous, Basic, Digest, Negotiate"/>
<!-- ... -->
</behavior>
</serviceBehaviors>
</behaviors>
Définissez également clientCredentialType sur "InheritedFromHost":
<bindings>
<basicHttpBinding>
<binding name="secureBinding">
<security mode="Transport">
<transport clientCredentialType="InheritedFromHost" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Les références:
Nous avons eu ce message d'erreur et pour nous, la solution était que les autorisations des fonctionnalités de mappage de gestionnaire n'avaient pas été activées pour Script. Vous pouvez l'activer dans IIS sous Mappages de gestionnaires> Modifier les autorisations des fonctionnalités, ou en ajoutant Script
à l'attribut accessPolicy
du nœud handlers
dans votre web.config:
<system.webServer>
<handlers accessPolicy="Script">
...
</handlers>
</system.webServer>