Authentification WCF - Une erreur s'est produite lors de la vérification de la sécurité du message
J'ai un problème de connexion à mon service WCF avec clientCredentialType="UserName"
.
Lorsque j'exécute le code ci-dessous j'obtiens une erreur
FaultException: Une erreur s'est produite lors de la vérification de sécurité pour le message.
En jouant avec certaines des valeurs contraignantes je reçois aussi des Access is denied.
.
Fiddler dit il n'y a pas d'en-tête d'autorisation et je ne trouve pas de nom d'utilisateur ou le mot de passe dans la demande.
Voici des extraits de ma config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<services>
<service name="InventoryServices.MobileAPI" behaviorConfiguration="customBehaviour">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="InventoryServices.IMobileAPI"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="customBehaviour">
<serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true" />
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="InventoryLibrary.Helpers.UserAuthentication,InventoryLibrary"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" proxyCredentialType="Basic" realm="MyRealm"/>
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
Mon nom d'utilisateur/mot de passe validateur ressemble à ceci:
public class UserAuthentication : UserNamePasswordValidator {
public override void Validate(string userName, string password) {
EntitiesContext db = new EntitiesContext();
db.Logs.Add(new DomainModels.Log() {
DateLogged = DateTime.Now,
Message = "hit auth",
Type = DomainModels.LogType.Info
});
db.SaveChanges();
try {
if (userName == "test" && password == "test123") {
Console.WriteLine("Authentic User");
}
}
catch (Exception ex) {
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
J'ai ceci comme un simple test sur mon service:
[OperationContract]
[XmlSerializerFormat]
void Test();
[PrincipalPermission(SecurityAction.Demand, Name = "test")]
public void Test() {
}
J'ai un auto-signature de certificat SSL sur mon serveur et je peux accéder à mon service/metadata.
Puis j'ai ajouté une référence de service dans une application console, et essayez de vous connecter au service avec ce code ci-dessous:
class Program {
static void Main(string[] args) {
Stuff.InitiateSSLTrust();
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.Realm = "MyRealm";
ServiceReference1.MobileAPIClient serviceProxy = new ServiceReference1.MobileAPIClient(binding, new EndpointAddress("https://xx.xx.xx.xx/InventoryServices.MobileApi.svc"));
serviceProxy.ClientCredentials.UserName.UserName = "test";
serviceProxy.ClientCredentials.UserName.Password = "test123";
try {
var a = serviceProxy.Login("a", "b");
}
catch (Exception ex) {
var ex2 = ex;
}
}
}
public class Stuff {
public static void InitiateSSLTrust() {
try {
//Change SSL checks so that all checks pass
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(
delegate { return true; }
);
}
catch (Exception ex) {
}
}
}
J'ai vérifié l'observateur d'événements sur le serveur et que cette erreur apparait à chaque demande:
MessageSecurityException: processeur de Sécurité n'a pas pu trouver un en-tête de sécurité dans le message. Ce pourrait être parce que le message est une non garantie de la faute ou parce qu'il n'y est une liaison à l'inadéquation entre les parties communicantes. Cela peut se produire si le service est configuré pour la sécurité et le client n'est pas à l'aide de la sécurité.
source d'informationauteur Smithy
Vous devez vous connecter pour publier un commentaire.
Vous spécifiez le côté client d'utiliser
BasicHttpSecurityMode.Transport
alors que le service s'attend àBasicHttpSecurityMode.TransportWithMessageCredential
. C'est un problème parce que le service est à la recherche pour les informations d'identification du client dans le Message SOAP en-Tête et le client sera de ne pas les envoyer avec la liaison configurée de cette façon.Par conséquent, c'est pourquoi le nom d'utilisateur/mot de passe n'est pas présent dans l'en-Tête de Message que vous êtes le témoin. Donc l'observateur d'événements est exact qu'il y a une liaison incompatibilité entre les parties communicantes.
Également définir la
ClientCredentialType
sur le client pourBasicHttpMessageCredentialType.UserName
pourMessage
niveau de sécurité. Par défautBasicHttpBinding
utiliseNone
qui sont des clients anonymes.Voici un extrait de code décrivant les changements ci-dessus: