Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Actualités

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

    View Cyril Durand's profile on LinkedIn

    hit counters

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
Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- ssdl view et TPT par Matthieu MEZIL le il y a 10 heures et 47 minutes

- L'injection SQL n'est PAS un problème QUE pour les développeurs web ! par CoqBlog le il y a 11 heures et 43 minutes

- Un outil pour réaliser des animations WPF basées sur des équations de Bézier par Perspective le il y a 15 heures et 6 minutes

- Sandcastle et CodePlex : le verdict par CoqBlog le il y a 15 heures et 57 minutes

- ssdl view et TPH par Matthieu MEZIL le il y a 17 heures et 39 minutes

- Webcasts sur le Parallel Framework disponibles par Matthieu MEZIL le il y a 19 heures et 25 minutes

- [Silverlight] - Comprendre et Débuter avec Silverlight par Danuz le 07-04-2008, 12:41

- SharePoint : Nouvel article sur l'exportation et Importation de sites SharePoint par Blog Technique de Romelard Fabrice le 07-04-2008, 01:00

- ImagineCup 2008 Final in Paris: Day 1 par Richard Clark le 07-03-2008, 22:48

- PowerShell : Comment utiliser un ENUM .NET dans un script PowerShell par Blog Technique de Romelard Fabrice le 07-03-2008, 18:09