Correct façon de communiquer WSSE élément usernametoken pour webservice SOAP
J'essaie de consommer un service web par le biais de son correspondant wsdl. Ce service dépend de l'authentification conforme à Les Services Web De Base De La Sécurité Le Profil De Sécurité 1.0 compris que la bonne xmls espace de noms de http://docs.oasis-open.org/wss/2004/01/oasis-200401wss-wssecurity-secext-1.0.xsd doivent être inclus dans la demande.
Exemple:
<wsse:UsernameToken xmlns:wsse='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' >
<wsse:Username>
Bob
</wsse:Username>
<wsse:Password Type='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText'>
1234
</wsse:Password>
</wsse:UsernameToken>
Mes premières tentatives étaient le long des lignes de Add Service Reference
ciblant le wsdl et par la réalisation de procurations de les utiliser en tant que tel
ServicePointManager.ServerCertificateValidationCallback =
(object s, X509Certificate certificate, X509Chain chain,
SslPolicyErrors sslPolicyErrors) => true;
var basicHttpBinding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
basicHttpBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Basic;
var endpoint = new EndpointAddress("https://secure-ausomxana.crmondemand.com/..."
using (var client = new ContactClient(basicHttpBinding, endpoint))
{
var credential = client.ClientCredentials.UserName;
credential.UserName = "bob";
credential.Password = "1234";
var input = ...
var output = client.ContactQueryPage(input);
}
Cependant tenter d'interroger les messages SOAP avec un violon, je vois qu'aucun élément usernametoken élément a été ajouté.
Quelle est la bonne manière de répondre à ce contrat?
Edit: à la suite de la réponse de @John Saunders, j'ai tenté de modifier mon code pour utiliser un wsHttpBinding
var wsHttpBinding = new WSHttpBinding(SecurityMode.Transport);
wsHttpBinding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.Basic;
À l'aide de cette liaison, le message SOAP devient
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing">
<s:Header>
<a:Action s:mustUnderstand="1">document/urn:crmondemand/ws/ecbs/contact/10/2004:ContactQueryPage</a:Action>
<a:MessageID>urn:uuid:17807f44-1fcasfdsfd</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://secure-ausomxana.crmondemand.com/Services/Integration</a:To>
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ContactQueryPage_Input xmlns="urn:crmondemand/ws/ecbs/contact/10/2004">
<ListOfContact xmlns="urn:/crmondemand/xml/Contact/Query">
<Contact>
<Id>1-asdfd</Id>
</Contact>
</ListOfContact>
</ContactQueryPage_Input>
</s:Body>
</s:Envelope>
Cela ajoute un élément d'en-Tête, par opposition à la wsse:UsernameToken
élément de référence pour l'original message soap à l'aide de la BasicHttpBinding est
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<ContactQueryPage_Input xmlns="urn:crmondemand/ws/ecbs/contact/10/2004">
<ListOfContact xmlns="urn:/crmondemand/xml/Contact/Query">
<Contact>
<Id>1-asdfds</Id>
</Contact>
</ListOfContact>
</ContactQueryPage_Input>
</s:Body>
</s:Envelope>
Si je change le contraignant à
var wsHttpBinding = new WSHttpBinding(SecurityMode.TransportWithMessageCredential);
wsHttpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
Le message SOAP-je obtenir est
<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<s:Header>
<a:Action s:mustUnderstand="1">http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</a:Action>
<a:MessageID>urn:uuid:eeb75457-f29e-4c65-b4bf-b580da26e0c5</a:MessageID>
<a:ReplyTo>
<a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
</a:ReplyTo>
<a:To s:mustUnderstand="1">https://secure-ausomxana.crmondemand.com/Services/Integration</a:To>
<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
<u:Timestamp u:Id="_0">
<u:Created>2011-05-02T13:30:09.360Z</u:Created>
<u:Expires>2011-05-02T13:35:09.360Z</u:Expires>
</u:Timestamp>
<o:UsernameToken u:Id="uuid-dc3605a0-6878-42f4-b1f2-37d5c04ed7b4-2">
<o:Username>Bob</o:Username>
<o:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">1234</o:Password>
</o:UsernameToken>
</o:Security>
</s:Header>
<s:Body>
<t:RequestSecurityToken xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
<t:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</t:TokenType>
<t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
<t:Entropy>
<t:BinarySecret u:Id="uuid-7195ad74-580b-4e52-9e2c-682e5a684345-1" Type="http://schemas.xmlsoap.org/ws/2005/02/trust/Nonce">bI4xuyKwZ8OkQYBRnz2LDNV+zhIOnl0nwP24yI1QAwA=</t:BinarySecret>
</t:Entropy>
<t:KeySize>256</t:KeySize>
</t:RequestSecurityToken>
</s:Body>
</s:Envelope>
Cela semble être très proche cependant il semble que cette réalité chiffrée le corps du message soap qui est quelque chose que je ne veux PAS arriver.
Si je spécifie wsHttpBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;
avec seulement l'aide de SecurityMode.Transport
, il va revenir à l'endroit où il dit son anonyme.
Quel est l'obstacle final je ne suis pas en mesure de clair sur ce point?
Solution finale: dit que j'avais poster ce cas, il aide à quelqu'un, il n'y a pas vraiment beaucoup de différent ici, d'autres le UserToken objet est enveloppé dans un nœud Sécurité qui est ce que mon fournisseur de service requis et semble être la façon dont sa sortie à partir de mes exemples précédents de ce que je pourrais obtenir généré.
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="Contact" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" allowCookies="false"
bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
maxBufferSize="524288" maxBufferPoolSize="524288" maxReceivedMessageSize="524288"
messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="65536" maxArrayLength="131072"
maxBytesPerRead="32768" maxNameTableCharCount="131072" />
<security mode="Transport">
<transport clientCredentialType="None" proxyCredentialType="None"
realm="" />
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://secure-ausomxana.crmondemand.com/Services/Integration"
binding="basicHttpBinding" bindingConfiguration="Contact"
contract="OnDemandContactService.Contact" name="OnDemand.Contact.Endpoint">
<headers>
<wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>USERNAME</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">PASSWORD</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</headers>
</endpoint>
</client>
</system.serviceModel>
Voir Avec C#, WCF SAVON consommateur qui utilise WSSE l'authentification en texte brut? pour la façon de le configurer à l'aide de code et pas de config
- Pourquoi avez-vous mis de transport de Base de la sécurité? Avez-vous besoin à la fois de transport et d'authentification de message?
- Pensez-vous que vous pourriez modifier cette option pour afficher une description concise de la recette? Il est difficile de le faire à travers le récit; je ne suis pas tout à fait clair sur ce que vous êtes en ajoutant et en soustrayant le récit se poursuit.
- La version concise est si vous attendez un message à utiliser
wsse:Security
vous devez utiliser l'allocation statique dans le web.config que j'ai en ma solution finale. Si vous avez besoin de modifier le nom d'utilisateur et le mot de passe, aussi loin que je peux dire que vous êtes SOL. - Merci. J'ai fini de poster mon propre question, et avec l'aide des autres, nous avons atterri sur une façon de faire: stackoverflow.com/questions/14327960/...
- la façon dont vous incluez la wsse de sécurité dans la configuration de l'en-tête est incroyable et a essayé de mettre en œuvre dans le code qui m'a pris une éternité.
- oui j'ai renoncé à essayer de la mettre en œuvre dans le code, je n'ai jamais réussi à le réussir, mais l'utilisation de ce bloc, c'est la voile en douceur pour l'authentification à la terrible api soap j'ai eu à traiter.
- cette question m'a vraiment aidé. merci de poser la question 🙂
- Étiez-vous nom d'utilisateur et le mot de passe codés en dur dans le fichier config, ou avez-vous une certaine façon de les mettre à jour au moment de l'exécution? Post très bien, très utile.
- j'ai jamais utilisé directement dans la config, le lien au bas de ma question peut vous permettre de modifier les informations d'identification au moment de l'exécution.
- Vieux post, mais nous avons encore des gens à l'aide de SAVON ici... 🙁 Le client les en-têtes m'a aidé à résoudre mon problème. Je n'ai pas besoin de l'appoint de transport et les paramètres de message dans la liaison. Merci
Vous devez vous connecter pour publier un commentaire.
Si vous devez envoyer un nom d'utilisateur sur HTTPS, vous pouvez utiliser l'approche standard (si votre WSDL est correctement définie cela devrait être créé automatiquement pour vous par l'ajout d'un service de référence):
Ar, vous pouvez définir la liaison dans le code:
Vous permettra de définir les informations d'identification dans proxy comme vous le faites maintenant:
Si vous avez seulement besoin d'élément usernametoken profil sur HTTP, sans aucune autre infrastructure WS-Security l'approche la plus simple est d'utiliser ClearUserNameBinding.
Si vous avez besoin de nom d'utilisateur et le mot de passe pour toutes les demandes du client, vous pouvez utiliser de simples basicHttpBinding sans aucune sécurité et inclure l'en-tête statique de configuration:
Si vous avez besoin de quelque chose de plus complexe montrer la partie pertinente de WSDL (security assertion) ou de l'échantillon de requête SOAP. Également mentionner si vous êtes obligé d'utiliser le protocole HTTP ou HTTPS.
MessageSecurityException
, regarde ma réponse ci-dessous. Vous devrez peut-être supprimer l'horodatage et de définir le type de contenu ainsi.@Ladislav réponse est correcte. Cependant, j'ai été faire un
MessageSecurityException
pour un SOAP 1.1 web service, j'ai été d'essayer de les utiliser. Suivant ce blog de Scott, Hanselman, j'ai été capable de le faire fonctionner. C'est le code que j'ai fini par utiliser:MessageCredentialType.UserName
enverra uniquement un nom d'utilisateur, ce qui serait utile pour un ApiKey style auth tout en violant le WS-normes de Sécurité. Je n'ai jamais compris pourquoi les gens les normes d'utilisation instantanément les violer, je pense que cela pourrait être que les normes WS-* sont si ridiculement arcanes aucune personne puisse raisonnablement comprendre de le suivre, même s'ils dire trop. Les normes WS-* définir l'architecture SOA arrière de la moitié d'une décennie. "Microservices" sont beaucoup plus proches de la fin de SOAClientCredentialType
UserName
comprend à la fois des nom d'utilisateur et Mot de passe propriétés. @ladislav réponse m'a aidé à obtenir sur la bonne voie. J'ai juste besoin d'ajouter un peu plus de changements pour le faire fonctionner pour le service web que je vais appeler. J'ai posté cela comme une réponse parce que 1) elle peut aider d'autres personnes ayant le même problème, et 2) je sais que ce doit être un commentaire en vertu de sa réponse, mais le code ne fonctionne pas bien dans un commentaire. Je suis d'accord que les normes WS-* sont trop complexes.Utilisation wsHttpBinding, pas basicHttpBinding.
En fait, vous devez simplement utiliser la fonction "Ajouter une Référence de Service" et le point le WSDL du service.
ClientCredentialType = BasicHttpMessageCredentialType.UserName
envoie le bon WS-Security-tête.