WCF: Ajout de nonce à UsernameToken

J’essaie de me connecter à un service Web, écrit en Java, mais il y a quelque chose que je ne peux pas comprendre.

Avec WCF et customBinding, presque tout semble aller pour le mieux, à l’exception d’une partie du message SOAP, car il manque les nœuds de partie Nonce et Created Evidemment, il me manque quelque chose, donc si vous pouviez me diriger dans la bonne direction, ce serait très apprécié.

Voici la liaison personnalisée:

      

Et voici la partie pertinente du message:

           

Et voici à quoi cela devrait ressembler:

   .. .. 6ApOnLn5Aq9KSH46pzzcZA== 2009-05-13T18:59:23.309Z   

La question est donc la suivante: comment puis-je introduire les éléments Nonce et Créé dans la partie sécurité?

Pour créer le nonce, j’ai dû changer quelques petites choses

Tout d’abord, ajouté une liaison personnalisée dans ma configuration

                

Ensuite, prenez ce code trouvé ici: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/4df3354f-0627-42d9-b5fb-6e880b60f8ee, puis modifiez-le pour créer le nonce hachage, codé en base 64)

 protected override void WriteTokenCore(System.Xml.XmlWriter writer, System.IdentityModel.Tokens.SecurityToken token) { Random r = new Random(); ssortingng tokennamespace = "o"; DateTime created = DateTime.Now; ssortingng createdStr = created.ToSsortingng("yyyy-MM-ddTHH:mm:ss.fffZ"); ssortingng nonce = Convert.ToBase64Ssortingng(Encoding.ASCII.GetBytes(SHA1Encrypt(created + r.Next().ToSsortingng()))); System.IdentityModel.Tokens.UserNameSecurityToken unToken = (System.IdentityModel.Tokens.UserNameSecurityToken)token; writer.WriteRaw(Ssortingng.Format( "<{0}:UsernameToken u:Id=\"" + token.Id + "\" xmlns:u=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\">" + "<{0}:Username>" + unToken.UserName + "" + "<{0}:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText\">" + unToken.Password + "" + "<{0}:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">" + nonce + "" + "" + createdStr + "", tokennamespace)); } protected Ssortingng ByteArrayToSsortingng(byte[] inputArray) { SsortingngBuilder output = new SsortingngBuilder(""); for (int i = 0; i < inputArray.Length; i++) { output.Append(inputArray[i].ToString("X2")); } return output.ToString(); } protected String SHA1Encrypt(String phrase) { UTF8Encoding encoder = new UTF8Encoding(); SHA1CryptoServiceProvider sha1Hasher = new SHA1CryptoServiceProvider(); byte[] hashedDataBytes = sha1Hasher.ComputeHash(encoder.GetBytes(phrase)); return ByteArrayToString(hashedDataBytes); } 

J’ai eu le même problème. À la place du sérialiseur de jeton personnalisé, j’ai utilisé MessageInspector pour append le nom d’ UsernameToken correct dans la méthode BeforeSendRequest . J’ai ensuite utilisé un comportement personnalisé pour appliquer le correctif.

L’ensemble du processus est documenté (avec un projet de démonstration ) dans mon billet de blog intitulé Prise en charge du résumé de mot de passe de profil WS-I dans un proxy client WCF . Alternativement, vous pouvez simplement lire le PDF .

Si vous souhaitez suivre ma progression jusqu’à la solution, vous la trouverez dans StackOverflow intitulée ” Erreur dans le service Web Axis 2 client WCF avec le schéma d’authentification WS-Security UsernameToken PasswordDigest “:

Cet article fournit un exemple d’intégration complète du profil UserNameToken avec un mot de passe digéré dans le pipeline de sécurité WCF.

Il est intéressant de noter que Rick Strahl a publié un article de blog (auquel il fait référence à cette question) dans lequel il explique tout cela très clairement et propose des solutions à la fois pour Password et PasswordDigest.

Je poste ceci parce que j’ai trouvé cet article à l’origine, je ne pouvais pas vraiment le suivre et j’ai trouvé le post de Rick beaucoup plus tard. Cela pourrait faire gagner du temps à certaines personnes.

WCF WSSecurity et WSE Nonce Authentication

J’ai également dû mettre un segment UserNameHeader dans l’en-tête du message SOAP:

    foouser foopass       

Cela a été accompli avec un en-tête de message personnalisé:

 public class UserNamePasswordHeader : MessageHeader { private readonly ssortingng _serviceUserEmail; private readonly ssortingng _serviceUserPassword; public UserNamePasswordHeader(ssortingng serviceUserEmail, ssortingng serviceUserPassword) { this._serviceUserEmail = serviceUserEmail; this._serviceUserPassword = serviceUserPassword; } public override ssortingng Name { get { return "UserNameHeader"; } } public override ssortingng Namespace { get { return "urn:bar:services"; } } protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) { writer.WriteElementSsortingng("UserName", _serviceUserEmail); writer.WriteElementSsortingng("Password", _serviceUserPassword); } } 

D’autres tags, tels que Nonce et Created , pourraient facilement être ajoutés.

La classe est utilisée comme suit:

 var service = new BarServiceClient(); service.ClientCredentials.ClientCertificate.Certificate = MessageSigningCertificate; using (new OperationContextScope(service.InnerChannel)) { OperationContext.Current.OutgoingMessageHeaders.Add( new UserNamePasswordHeader(serviceUserEmail, serviceUserPassword)); try { var response = service.GetUserList(); return response; } finally { service.Close(); } } 

Remarque: MessageSigningCertificate est un certificate X.509, je l’ai lu dans un fichier:

 private static X509Certificate2 LoadCertificateFromFile(ssortingng pfxFilePath, ssortingng privateKeyPassword) { // Load the certificatee from a file, specifying the password var certificatee = new X509Certificate2(pfxFilePath, privateKeyPassword); return certificatee; }