Introduction

Les webservices permettent à une application d'appeler à distance une méthode exposée sur un serveur. Les informations échangées transitent par le protocole HTTP et sont formatées en données XML selon la norme SOAP. Ainsi, il est possible de faire communiquer ensemble des applications développées avec des technologies différentes.
Un inconvénient majeur des webservices aujourd'hui est l'absence de vraie sécurité dans les normes officielles. Les sociétés se mettent alors à proposer leurs propres solutions pour pallier à ce manque. Cependant, ces initiatives restent souvent propriétaires et font disparaître l'intérêt principal des webservices : la compatibilité universelle du moment qu'une technologie sait lire et écrire du xml et utiliser les sockets.
Cet article a pour but de proposer une solution pour sécuriser les webservices en faisant transiter les données par le protocole HTTPS. L'ajout de couche SSL sur HTTP est supporté par la majorité des serveurs web modernes comme IIS ou Apache par exemple.

Nous utiliserons IIS comme serveur web et implémenterons un webservice en ASP.NET qui sera ensuite consommé dans une Winform cliente.

La configuration utilisée pour ce tutorial est :
- Windows XP Pro SP1
- IIS 5.1 avec support de ASP.NET
- Visual Studio .NET 2003

Pour avoir des compléments sur l'utilisation des webservices en .NET :
- http://morpheus.developpez.com/WebServicesCSharp/
- http://stephaneey.developpez.com/tutoriel/dotnet/webservice/

Un autre article concernant la mise en place du SSL sous IIS 5.0 dans un domaine Windows 2000 :
- http://webman.developpez.com/articles/windows/ssl/

1. Partie serveur

1.1. Création du WebService

Image non disponible Veillez à ce que IIS soit démarré en local sur votre machine
Image non disponible Ouvrez Visual Studio .NET
Image non disponible Faites "Fichier > Nouveau > Projet" et choisissez "Projets Visual C# > Service Web ASP.NET"
Image non disponible Indiquez dans Emplacement : "http://localhost/WebServicesHTTPS" puis "Ok"

Une nouvelle Solution contenant un nouveau Projet est créée.
Un fichier "Service1.asmx" apparaît aussi, il contiendra la définition de notre Webservice.

Image non disponible Faites un clic droit sur Service1.asmx puis "Afficher le code"

A cet instant, vous devriez avoir votre projet qui ressemble à ça :

Image non disponible

Nous allons maintenant écrire une WebMethod qui va prendre en paramètre deux entiers, les additionner et retourner le résultat.

Remplacez dans le code de Service1.asmx :

C#
Sélectionnez

//	[WebMethod]
//	public string HelloWorld()
//	{
//		return "Hello World";
//	}

Par :

C#
Sélectionnez

[WebMethod]
public int AddInteger(int a, int b)
{
	return a+b;
}

La mention [WebMethod] permet d'indiquer que AddInteger doit être accessible à distance.

Image non disponible Appuyez sur "F5", le webservice se compile et la fenêtre de votre navigateur par défaut se lance.
Image non disponible Vous pouvez alors tester votre webservice en cliquant sur "AddInteger"

Nous allons maintenant sécuriser ce webservice. Dans un premier temps, un certificat va être créé puis intégré dans IIS et associé à notre répertoire virtuel "http://localhost/WebServicesHTTPS".

1.2. Création du certificat

Nous allons maintenant créer un certificat qui sera stocké du côté du serveur uniquement et permettra d'authoriser la communication via HTTPS lors de la connexion d'un client.

Image non disponible Rendez-vous sur : http://www.slproweb.com/products/Win32OpenSSL.html
Image non disponible Téléchargez et installez : "Win32OpenSSL-v0.9.7e.exe" (fichier le plus récent au moment d'écrire cet article). On admettra que l'installation s'est déroulée dans "C:\OpenSSL".
Image non disponible Lancez une fenêtre DOS et placez-vous dans le répertoire "C:\OpenSSL\bin"
Image non disponible Tapez la commande : "openssl genrsa -des3 -out TutoHTTPS.key 1024".
Image non disponible Indiquez une phrase comme demandé et ne l'oubliez pas.

Une clé privée "TutoHTTPS.key" est créée, ne la divulguez pas ... elle est privée.

Image non disponible Tapez la commande suivante dans la fenêtre DOS : "openssl req -new -key TutoHTTPS.key -x509 -days 1095 -out TutoHTTPS.crt"
Image non disponible Entrez la phrase utilisée dans la génération de TutoHTTPS.key
Image non disponible Entrez ensuite les quelques informations qui vous sont demandées, mettez un "." lorsque vous ne souhaitez pas répondre.

Le fichier "TutoHTTPS.crt" créé correspond à l'authorité de certification et est diffusable librement.

La contenu de votre fenêtre DOS devrait ressembler à ça :

Image non disponible

1.3. Configuration de IIS

Image non disponible Sous Windows, allez dans "Panneau de configuration > Outils d'aministration > Service Internet (IIS)"
Image non disponible Faites un "clic droit" sur "Site web par défaut" puis "Propriétés"
Image non disponible Sélectionnez l'onglet "Sécurité du répertoire" puis cliquez sur le bouton "Certificat de serveur ..."

Image non disponible

Image non disponible Dans l'assistant, choisissez de "Créer un certificat", donnez lui comme Nom : "TutoHTTPSIIS".
Image non disponible Suivez ensuite les instructions, laissez comme fichier de demande : "c:\certreq.txt" et allez jusqu'à cliquez sur "Terminer"

Nous allons maintenant signer le certificat généré par IIS en utilisant les clés précédemment créées.

Image non disponible Lancez une fenêtre DOS, placez-vous dans "c:\OpenSSL\bin"
Image non disponible Tapez : "openssl x509 -req -days 365 -in c:\certreq.txt -CA TutoHTTPS.crt -CAkey TutoHTTPS.key -CAcreateserial -out TutoHTTPSIIS.crt"
Image non disponible Entrez votre phrase secrète.

Le fichier "TutoHTTPSIIS.crt" est maintenant créé dans "c:\OpenSSL\bin"

La fenêtre DOS correspondant à ces manipulations devrait ressembler à ça :

Image non disponible

Note : la chaine "minosis-small" correspond au nom DNS de l'ordinateur sur lequel ce tutorial a été écrit.

Image non disponible De nouveau, allez dans "Panneau de configuration > Outils d'aministration > Service Internet (IIS)"
Image non disponible Faites un "clic droit" sur "Site web par défaut" puis "Propriétés"
Image non disponible Sélectionnez l'onglet "Sécurité du répertoire" puis cliquez sur le bouton "Certificat de serveur ..."
Image non disponible Choisissez dans l'assistant de "Traiter la demande en attente et installer le certificat"
Image non disponible Sélectionnez ensuite le nouveau certificat : "C:\OpenSSL\bin\TutoHTTPSIIS.crt"
Image non disponible Puis continuez l'assistant jusqu'à "Terminer"
Image non disponible Cliquez sur OK dans la fenêtre de propriétés.

Le certificat de serveur est maintenant installé sur IIS.
Utilisons ce certificat sur le répertoire virtuel du webservice "WebServicesHTTPS"

Image non disponible Dans "Site Web par défaut", faites un clic droit sur le répertoire virtuel "WebServicesHTTPS" puis "Propriétés"
Image non disponible Sélectionnez l'onglet "Sécurité du répertoire" puis "Communications sécurisées > Modifier..."
Image non disponible Dans la fenêtre qui apparaît, cochez "Requérir un canal sécurisé" puis "Ok". "Ok" encore dans la fenêtre de propriétés puis "Ok" dans la fenêtre "Héritages outrepassés"

Image non disponible

1.4. Gestion de l'authentification (Facultatif)

Cette étape est facultative, elle permet d'associer un utilisateur Windows à la connexion HTTPS au webservice et donc de gérer l'authentification de manière non anonyme (par défaut IIS associe toute connexion à un répertoire virtuel à l'utilisateur ASPNET).
Si cette étape n'est pas suivie, alors la liaison HTTPS servira uniquement à garantir la confidentialité des données.

Dans le code de l'étape 2.3, nous dissocierons les deux cas : avec ou sans authentification.

Image non disponible Dans "Site Web par défaut", faites un clic droit sur le répertoire virtuel "WebServicesHTTPS" puis "Propriétés"
Image non disponible Sélectionnez l'onglet "Sécurité du répertoire" puis "Connexions anonymes et contrôle d'authentification > Modifier..."
Image non disponible Dans la fenêtre qui apparaît, décochez "Connexion anonyme"

Image non disponible

Créons un utilisateur sous Windows qui sera utilisé pour l'authentification dans notre exemple.

Image non disponible Sous Windows, allez dans "Panneau de configuration > Outils d'aministration > Gestion de l'ordinateur"
Image non disponible Déroulez "Utilisateurs et groupes locaux" puis cliquez sur le répertoire "Utilisateurs"
Image non disponible Sélectionnez le menu "Action > Nouvel utilisateur..."
Image non disponible Indiquez les paramètres suivants et cliquez sur "Créer" et fermez la fenêtre de "Gestion de l'ordinateur" :

- Nom d'utilisateur : userHTTPS
- Nom complet : userHTTPS
- Mot de passe : titi
- Confirmer le mot de passe : titi
- "L'utilisateur doit changer de mot de passe ..." : Décoché
- "L'utilisateur ne peut pas changer de mot de passe" : Coché
- "Le mot de passe n'expire jamais" : Coché
- "Le compte est désactivé" : Décoché

Image non disponible

2. Partie cliente

2.1. Conception de l'interface, WinForm

Image non disponible Ouvrez la solution "WebServicesHTTPS" dans Visual Studio si vous l'aviez fermée
Image non disponible Faites "Fichier > Nouveau > Projet..." et choisissez "Projets Visual C# > Application Windows"
Image non disponible Cochez "Ajouter à la solution" et donnez comme nom : "WinCalculService", puis "Ok"
Image non disponible Placez sur la Form, les contrôles comme ci-dessous :

Image non disponible

2.2. Ajout du WebService en référence web

Référençons le Webservice :

Image non disponible Dans le projet "WinCalculService", faites un clic droit sur "Référence" puis "Ajouter une référence Web... "
Image non disponible Dans la fenêtre qui apparaît, indiquez dans le champ URL : "https://localhost/WebservicesHTTPS/Service1.asmx" puis cliquez sur "Allez à"
Image non disponible Répondez "Oui" à chaque fenêtre de demande de confirmation
Image non disponible Lorsque le Webservice est chargé (le lien vers AddInteger doit apparaître dans la zone centrale), indiquez comme "Nom de la référence Web" la valeur : "com.minosis.services" (c'est un exemple bien sûr)
Image non disponible Cliquez sur "Ajouter la référence"

Dans le projet, un dossier "Web References" a dû apparaître avec en contenu : "com.minosis.services".

Image non disponible

2.3. Ecriture du code

Image non disponible Dans la Form1, double-cliquez sur le bouton "button1", la fenêtre de code s'ouvre
Image non disponible Ajouter en haut, les appels aux références suivants :

C#
Sélectionnez

using System.Web.Services;
using System.Web.Services.Protocols;
using System.Security.Cryptography.X509Certificates;
using System.Net;

Image non disponible Remplacez ce code :

C#
Sélectionnez

private void button1_Click(object sender, System.EventArgs e)
{
}

Par :

1er cas : Vous n'avez pas suivi l'étape 1.4, donc pas de gestion de l'authentification, mettez ce code :

C#
Sélectionnez

private void button1_Click(object sender, System.EventArgs e)
{
	try
	{
		// On indique la validation automatique des demandes d'acceptation des certificats
		System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatesPolicy(); 
		
		// Instanciation de la classe proxy permettant l'appel distant au Webservice
		com.minosis.services.Service1 serviceAdd = new com.minosis.services.Service1();

		// Conversion des valeurs String en int 
		int a = Int32.Parse(textBox1.Text);
		int b = Int32.Parse(textBox2.Text);

		// Appel à la méthode distante. Son résultat étant un int, on le convertit en String
		textBox3.Text = serviceAdd.AddInteger(a,b).ToString();
	}
	catch // Si une exception est levée, on affiche "Erreur" dans la zone de résultat
	{
		textBox3.Text = "Erreur";
	}
}

// Classe implémentant l'interface System.Net.ICertificatePolicy
// Permet de toujours autoriser l'acceptation des certificats
public class TrustAllCertificatesPolicy : System.Net.ICertificatePolicy 
{ 
	public bool CheckValidationResult(ServicePoint sp, 
		X509Certificate cert,WebRequest req, int problem) 
	{ 
		return true;
	} 
} 

Par :

2ème cas : Vous avez suivi l'étape 1.4, l'application devra s'identifier avec l'utilisateur "userHTTPS"

C#
Sélectionnez

private void button1_Click(object sender, System.EventArgs e)
{
	try
	{
		// On indique la validation automatique des demandes d'acceptation des certificats
		System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatesPolicy(); 
		
		// Instanciation de la classe proxy permettant l'appel distant au Webservice
		com.minosis.services.Service1 serviceAdd = new com.minosis.services.Service1();

		// Authentification avec l'utilisateur dédié au webservice : userHTTPS
		serviceAdd.Credentials = new NetworkCredential("userHTTPS","titi");

		// Conversion des valeurs String en int 
		int a = Int32.Parse(textBox1.Text);
		int b = Int32.Parse(textBox2.Text);

		// Appel à la méthode distante. Son résultat étant un int, on le convertit en String
		textBox3.Text = serviceAdd.AddInteger(a,b).ToString();
	}
	catch // Si une exception est levée, on affiche "Erreur" dans la zone de résultat
	{
		textBox3.Text = "Erreur";
	}
}

// Classe implémentant l'interface System.Net.ICertificatePolicy
// Permet de toujours autoriser l'acceptation des certificats
public class TrustAllCertificatesPolicy : System.Net.ICertificatePolicy 
{ 
	public bool CheckValidationResult(ServicePoint sp, 
		X509Certificate cert,WebRequest req, int problem) 
	{ 
		return true;
	} 
} 

Vous remarquerez que seule une ligne supplémentaire est nécessaire pour cette authentification :

C#
Sélectionnez

// Authentification avec l'utilisateur dédié au webservice : userHTTPS
serviceAdd.Credentials = new NetworkCredential("userHTTPS","titi");

Pour tester maintenant :
Image non disponible Faites un clic droit sur le projet "WinCalculService" puis "Déboguer > Démarrer une nouvelle instance"

Si la compilation s'est bien déroulée, la WinForm créée devrait s'afficher et vous pouvez ainsi tester la consommation du webservice "WebServicesHTTPS".

Tout s'est déroulé en local sur la machine de développement. Evidemment, le but final est d'avoir chacun des projets séparés sur des machines distantes.

Téléchargements

Téléchargez la version pdf de cet article.
Téléchargez les sources C# de cet article (la configuration de IIS et du certificat doit être cependant suivie).

Merci à Freegreg pour la relecture.