Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Atteint de JavaScriptite Aiguë [Cyril Durand]

Expert ASP.net Ajax et WCF, Cyril Durand parle dans son blog de point techniques sur ASP.net, ASP.net Ajax, JavaScript, WCF et .net en général. Cyril est également consultant indépendant, n'hésitez pas à le contacter pour de l'assistance sur vos projets

Actualités

  • Blog de Cyril DURAND, passionné de JavaScript, Ajax, ASP.net et tout ce qui touche au developpement Web Client-Side.

    N'hésitez pas à me contacter pour vos projets .net : architecture, accompagnement, formation, ...

    View Cyril Durand's profile on LinkedIn
    hit counters


    Expertise Commerce server et BizTalk

SoapHeader : s'authentifier proprement a un WebService SOAP

Les WebServices utilisent le protocole SOAP, ce protocole permet d'échanger des données facilement. Une enveloppe SOAP est composée de plusieurs parties : le Header et le Body. La plupart du temps nous utilisons seulement la partie body.

Voici un exemple de requête SOAP

<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetProduct xmlns="http://tempuri.org/"> <productID>int</productID> </GetProduct> </soap:Body> </soap:Envelope>

et voici une réponse possible :

<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetProductResponse xmlns="http://tempuri.org/"> <GetProductResult> <ProductID>int</ProductID> <ProductName>string</ProductName> <Description>string</Description> <Price>int</Price> </GetProductResult> </GetProductResponse> </soap:Body> </soap:Envelope>

ASP.net permet de gérer très facilement les WebServices, le code .net correspondant est :

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WebService : System.Web.Services.WebService { [WebMethod] public Product GetProduct(int productID) { return new Product(productID, "title", "description", 100); } }

Mais imaginons maintenant que je veuille m'authentifier auprès de ce WebService ? Une des solutions consiste à passer les login/pass en paramètre de la méthode GetProduct ce qui n'est pas très propre.

L'autre solution est d'utiliser l'en-tete d'une requête SOAP. Pour cela on va tout d'abord créer un nouveau type qui hérite de SoapHeader, ce type contiendra les informations de connexion :

public class CredentialHeader : SoapHeader { public CredentialHeader() : base() { } public CredentialHeader(String userName, String password) : base() { this._userName = userName; this._password = password; } private String _userName; private String _password; public String UserName { get { return _userName; } set { _userName = value; } } public String Password { get { return _password; } set { _password = value; } } }

Ensuite nous rajoutons l'attribute SoapHeaderAttribute sur la WebMethod qui prend en argument le nom d'une variable public du type que l'on vient de créer.

Ainsi lorsqu'un client enverra une requête SOAP contenant les informations de connexion dans l'en-tête, notre variable Authentication sera automatiquement renseigné, nous pouvons alors tester si le login/pass est correcte dans notre WebMethod.

[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] public class WebService : System.Web.Services.WebService { public CredentialHeader Authentication; [WebMethod] [SoapHeader("Authentication")] public Product GetProduct(int productID) { if (Authentication.UserName == "Cyril" && Authentication.Password == "porcinet") return new Product(productID, "title", "description", 100); else throw new System.Security.Authentication.InvalidCredentialException(); } }

Notre requête SOAP devra donc contenir les informations de connexions dans le header. Cela se traduit par une requête de ce type :

<?xml version="1.0" encoding="utf-8"?> <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Header> <CredentialHeader xmlns="http://tempuri.org/"> <UserName>string</UserName> <Password>string</Password> </CredentialHeader> </soap:Header> <soap:Body> <GetProduct xmlns="http://tempuri.org/"> <productID>int</productID> </GetProduct> </soap:Body> </soap:Envelope>

Maintenant que nous savons comment demander des paramètres dans le header d'une requête SOAP, voyons comment les envoyer. Pour cela nous référençons classiquement notre i en faisant un "Add Web Reference" dans Visual Studio. Puis lorsque nous instancions notre classe proxy, nous avons la possibilité de renseigner une propriété CredentialHeaderValue de type CredentialHeader :

WS.WebService ws = new WS.WebService(); ws.CredentialHeaderValue = new WS.CredentialHeader(); ws.CredentialHeaderValue.UserName = "Cyril"; ws.CredentialHeaderValue.Password = "porcinet"; Console.WriteLine(ws.GetProduct(10).Price);

L'attribut SoapHeaderAttribute permet également de spécifier la direction de l'en-tête, ce qui permet d'avoir plusieurs variables de retour lors de l'appel à un WebService.


Merci à chimerique qui m'a fait découvrir les header SOAP grâce à sa question sur le forum ASP de CodeS-SourceS : Web Service + Sécurité
Posted: samedi 7 avril 2007 02:47 par cyril
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Commentaires

davestar a dit :

bonjour,

je ne connaissais pas ce mode, j'utilisais les sessions sur le webservice pour pouvoir garder une identification avec une webmethode d'identification avant l'utilisation du web service.

Je vais tester ça

# avril 7, 2007 10:29

arno a dit :

Cette méthode fonctionne très bien et est éprouvée. Toutefois, elle n'est pas standardisée et il est donc préférable de s'appuyer sur les normes WS-* avec une implémentation de WS-Security qui permet justement de véhiculer un login / password puis de générer un token une fois authentifié.

# avril 7, 2007 12:16

ebartsoft a dit :

porcinet... ça c'est du mots de passe

encore un fan du gros ours a tshirtrouge !

;)

# avril 7, 2007 12:56

cyril a dit :

arno tu peux détailler ? comment ca elle n'est pas standardisé ? la balise soap:header fait partie du standard SOAP.

# avril 7, 2007 12:59

Kangoo a dit :

Pour compléter le commentaire d'Arno, il est à noter aussi que c'est ce mécanisme qui est utilisé par WCF lorsque tu veux sécuriser tes appels et que tu utilises un binding SOAP (WsHttpBindging)

# avril 7, 2007 13:04

arno a dit :

Le SoapHeader en lui-même est bien entendu standardisé. C'est la méthode d'authentification utilisée qui ne l'est pas. Pour cela, il faut utiliser les normes WS-* qui propose un ensemble de spécifications autour des Web Services et permettent de garantir une normalisation des échanges applicatifs. Objectif interoperabilité.

Ces normes sont implémentées dans WSE par Microsoft et on y retrouve donc : WS-Security, WS-Attachment, WS-ReliableMessaging ...

Comme le dit Kangoo, WCF repose sur ces normes et implémentes donc l'ensemble des spécifications.

Web Services Specifications : http://msdn2.microsoft.com/en-us/library/ms951274.aspx

# avril 7, 2007 13:36

emac a dit :

Comment faire la même chose avec WCF (en utilisant quelque chose de standardisé) ?

# novembre 8, 2008 15:32

cyril a dit :

La sécurité en WCF est une importante partie de WCF, il existe de nombreuses méthodes d'authentification / authorization qui sont beaucoup plus poussé que ce très simple exemple.

Pour avoir un comportement similaire, au niveau du binding, il faut mettre l'attribut mode à Message au niveau de la balise security puis mettre le clientCredentialType à UserName

<security mode="Message">

  <message clientCredentialType="UserName" />

</security>

# novembre 8, 2008 19:12

Kikuts a dit :

Magique :) avec ça j'ai pu supprimer mes login password des méthodes de mes services web ^^

Aurais tu fait un article sur le binding avec le message ?

Cet article à 3 ans, mais il ne veillit pas ! Toujours d'actualité :)

Merci beaucoup pour le partage ! C'est plus simple que la msdn.

# mai 4, 2011 13:34
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- [PowerShell 3] Télécharger et installer la documentation en ligne par Blog de SPBrouillet (Pierrick BROUILLET) le il y a 18 heures et 38 minutes

- [#SharePoint 2010][#SQLServer 2012] AlwaysOn pour SharePoint (1/4) : Configuration (1ère partie)… par Le blog de Patrick [MVP SharePoint] le 05-16-2012, 12:10

- Job Day @MIC Brussels - .Net Developers on Mobile applications par Le Blog (Vert) d'Arnaud JUND le 05-15-2012, 20:26

- [SharePoint 2010] – SharePoint 2010, Windows (Server) 8 et des erreurs IIS sont dans une VM… par Blog de SPBrouillet (Pierrick BROUILLET) le 05-14-2012, 12:10

- [Event] Windows Azure dev Camp le 20 juin! par Fathi Bellahcene le 05-13-2012, 09:29

- Comment redimensionner une image avec WinRT : plusieurs solutions par Richard Clark le 05-11-2012, 15:43

- Event : Swiss SharePoint Club Meeting #20 à Yverdon par Blog Technique de Romelard Fabrice le 05-11-2012, 15:24

- Réflechissons un peu ce matin à propos des ORM par Richard Clark le 05-11-2012, 08:48

- #SharePoint Solutions Roadshow le 5 juin à Issy ! par Le blog de Patrick [MVP SharePoint] le 05-09-2012, 15:10

- SharePoint : Mes alertes ne marchent pas … Que faire ? Comment réparer ou agir ? par The Mit's Blog le 05-08-2012, 14:59