Votre question

Web Services Security

Tags :
  • web
  • Programmation
Dernière réponse : dans Programmation
26 Février 2007 15:05:22

Pour une fois c'est moi qui vais poser des questions ( ca sent la vengeance de certains xD ) .

Bon actuellement , je travaille depuis peu sur l'utilisation de Web Services en java .
J'ai bien évidemment des normes de sécurité à respecter au sein de l'entreprise dans laquelle je travaille et je me dois donc de sécuriser un maximum ce web Services.

Ce web Service est accessible depuis l'intranet comme de l'extranet .

J'essaie depuis peu d'implémenter wss4j dans une simple application de test ( la vrai application est terminée ), seulement après des recherches sur le net , je dois bien dire que je n'arrive pas à cerné la facon de faire .

Avant d'aller plus loin , y a t'il d'autre manière de sécuriser un ws et à quel niveau ?

Sinon pour faire un peu d'office de tuto par la même occasion , on va partir d'un exemple simple .

Pour ma part je suis sous Eclipse Lomboz avec le Wtp à jour et le serveur se trouve être Jonas ^^ .

Je ne vais pas mettre la description du fichier de deploy , vu qu'il se génère grace à eclipse .

essai.java
  1. public class Essai {
  2.  
  3. public String message(String msg){
  4. return msg;
  5. }
  6.  
  7. }


Un simple web Service qui renvoit la chaine envoyé lors de l'appel

Son fichier wsdl

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <wsdl:definitions targetNamespace="http://DefaultNamespace" xmlns:apachesoap="<a href="http://xml.apache.org/xml-soap" rel="nofollow" target="_blank">http://xml.apache.org/xml-soap</a>" xmlns:impl="http://DefaultNamespace" xmlns:intf="http://DefaultNamespace" xmlns:wsdl="<a href="http://schemas.xmlsoap.org/wsdl/" rel="nofollow" target="_blank">http://schemas.xmlsoap.org/wsdl/</a>" xmlns:wsdlsoap="<a href="http://schemas.xmlsoap.org/wsdl/soap/" rel="nofollow" target="_blank">http://schemas.xmlsoap.org/wsdl/soap/</a>" xmlns:xsd="<a href="http://www.w3.org/2001/XMLSchema" rel="nofollow" target="_blank">http://www.w3.org/2001/XMLSchema</a>">
  3. <!--WSDL created by Apache Axis version: 1.3
  4. Built on Oct 05, 2005 (05:23:37 EDT)-->
  5. <wsdl:types>
  6. <schema elementFormDefault="qualified" targetNamespace="http://DefaultNamespace" xmlns="<a href="http://www.w3.org/2001/XMLSchema" rel="nofollow" target="_blank">http://www.w3.org/2001/XMLSchema</a>">
  7. <element name="message">
  8. <complexType>
  9. <sequence>
  10. <element name="msg" type="xsd:string"/>
  11. </sequence>
  12. </complexType>
  13. </element>
  14. <element name="messageResponse">
  15. <complexType>
  16. <sequence>
  17. <element name="messageReturn" type="xsd:string"/>
  18. </sequence>
  19. </complexType>
  20. </element>
  21. </schema>
  22. </wsdl:types>
  23.  
  24. <wsdl:message name="messageResponse">
  25.  
  26. <wsdl:part element="impl:messageResponse" name="parameters"/>
  27.  
  28. </wsdl:message>
  29.  
  30. <wsdl:message name="messageRequest">
  31.  
  32. <wsdl:part element="impl:message" name="parameters"/>
  33.  
  34. </wsdl:message>
  35.  
  36. <wsdl:portType name="Essai">
  37.  
  38. <wsdl:operation name="message">
  39.  
  40. <wsdl:input message="impl:messageRequest" name="messageRequest"/>
  41.  
  42. <wsdl:output message="impl:messageResponse" name="messageResponse"/>
  43.  
  44. </wsdl:operation>
  45.  
  46. </wsdl:portType>
  47.  
  48. <wsdl:binding name="EssaiSoapBinding" type="impl:Essai">
  49.  
  50. <wsdlsoap:binding style="document" transport="<a href="http://schemas.xmlsoap.org/soap/http" rel="nofollow" target="_blank">http://schemas.xmlsoap.org/soap/http</a>"/>
  51.  
  52. <wsdl:operation name="message">
  53.  
  54. <wsdlsoap:operation soapAction=""/>
  55.  
  56. <wsdl:input name="messageRequest">
  57.  
  58. <wsdlsoap:body use="literal"/>
  59.  
  60. </wsdl:input>
  61.  
  62. <wsdl:output name="messageResponse">
  63.  
  64. <wsdlsoap:body use="literal"/>
  65.  
  66. </wsdl:output>
  67.  
  68. </wsdl:operation>
  69.  
  70. </wsdl:binding>
  71.  
  72. <wsdl:service name="EssaiService">
  73.  
  74. <wsdl:port binding="impl:EssaiSoapBinding" name="Essai">
  75.  
  76. <wsdlsoap:address location="http://localhost:9000/MailWs/services/Essai"/>
  77.  
  78. </wsdl:port>
  79.  
  80. </wsdl:service>
  81.  
  82. </wsdl:definitions>


( ca fait con mais bon autant partir de quelque chose de très simple ^^ )

Autres pages sur : web services security

26 Février 2007 15:40:33

En général, mes WS sont tous en intranet, donc la sécurité importe peu car on considère que le réseau est sécurisé.
Par contre, dernièrement, j'ai dû publier 2 WS dans une DMZ, le premier privé, le second en accès public sur internet.

Pour le premier, filtrage des ip autres que celle du serveur web qui consomme le WS + blocage dans le routeur.

Pour le second, en réalité, j'ai mis en place une sécurité à plusieurs niveaux :
Les données. Donc achat d'un certificat verisign , et chiffrage en SSL.
Ensuite, vient le problème de la sécurité de la connexion en elle-même. Comment empêcher quelqu'un qui n'a pas le droit a accéder au WS.
Et bien, avec le protocole kerberos sur https.
En gros : ton client s'authentifie par kerberos avec un mot de passe (que saisie l'utilisateur). Tout le processus d'identification se fait dans un tunnel SSL pour ne rien laisser en clair.
26 Février 2007 15:42:38

une fois authentifié par le serveur via kerberos, tu as un jeton (TokenID) que tu passes au WS métier comme étant un des paramètres. Ce token est valide pour 1 appel seulement et associe la sécurité kerberos, SSL, l'IP du client et un numéro aléatoire de séquence (même principe que la pile ip)
Contenus similaires
26 Février 2007 17:04:22

Ah :)  j'attendais cette réponse avec impatience ^^ .

J'ai omis de préciser que les clients ne sont pas obligatoirement des applications Java , est-ce que Kerberos est alors un frein dans ce cas la ?

Le principe du ssl je l'avais compris , le hic c'est que je n'ai pas réussi à le mettre en pratique . Au niveau de kerberos j'imagine qu'il doit y avoir de la doc la dessus sur le web , je vais matter de suite .

Quand même avec tout les sites que j'ai consulté que ce soit en anglais , francais et même espagnole , j'en ai vu aucun mentionant kerberos , je suis outré xD .

Je te tiens au courant de la suite .
26 Février 2007 17:19:16

C'est certainement parce qu'un web service est "ouvert" par définition.
Si tu veux de la sécurité, à toi d'encapsuler le service que tu fournis.
J'ai choisi kerberos car c'est un protocole d'authentification fiable, éprouvé et dont on trouve des librairies dans à peu près tous les langages.

En gros, ton web service "métier" reste ouvert, mais est sécurisé par le protocole SSL pour ne pas que l'on puisse espionner les échanges.
Mais rien n'interdit à quelqu'un de l'utiliser même s'il n'en a pas le droit.
Kerberos va te permettre de t'assurer que la personne qui va utiliser ton métier est bien une personne dûment certifiée et connue.

En résumé, tu as 2 WS :
  1. public class Token {
  2. private String _tokenID; // Mettre un getter et un setter
  3. private long _sequence; // Mettre un getter et un setter
  4. }
  5.  
  6. public Token TrustMe(String userID, String pwd); // WS d'authentification
  7.  
  8. public String GetMessage(Token token, String msg); // WS métier


Dans la méthode web service TrustMe, tu créés le token, un genre de md5, et un numéro de séquence incrémentale.
Ce dernier point est totalement optionnel. J'utilise ça pour éviter le spoofing car même si on capture le tokenID, ce qui est très peu probable, il y a longtemps que le numéro de la séquence sera obsolète.

Il faut ensuite mémoriser dans une Hashtable l'objet TokenID et l'adresse ip du client.
Ensuite tu renvois à l'appelant ton objet Token fraichement créé.

Le client invoque ensuite ton WS métier et te passe le token pour prouver qu'il a bien le droit.
La première chose à faire est de vérifier avec la Hashtable que tu as en session que le token est valable et que l'ip correspond toujours. Si c'est le cas, tu poursuis le traitement, sinon, tu le jettes.
26 Février 2007 18:34:15

Ah la méthode du jeton ( token ring ca me rappelle de vieilles notions de réseau xD ) , de plus on peut s'en servir pour tout les webs services déployés .
Maintenant il y a un autre problème , c'est le cryptage de donnée.
Dans l'enveloppe SOAP , tout apparaît en clair . Envoyer de simple information c'est pas dérangeant , mais une fois qu'il s'agit d'authentification , c'est pas le top .
26 Février 2007 20:04:15

C'est pour cette raison que le tout est encapsulé dans SSL via https.
De cette manière, même le processus d'authentification est chiffré, puis le transfert des données aussi.
26 Février 2007 20:19:29

Hum , je viens de looker à propos de kerberos sur wikipédia , c'est un protocole d'identification réseau. La seule chose que j'ai trouvé par rapport à java , c'est qu'il fait partit du package javax.

Question de lien sur la doc pour implémenter ca , je suis à sec :/  .

Tu n'as pas un lien de doc ?

Je réedit une nouvelle fois .

Il semblerait que c'est de ce coté que la solution se trouve : "Single Sign-on Using Kerberos".
Je continue de chercher ^^.

Edition : Et bien je cherche , je cherche , mais je ne vois aucun code d'exemple d'implémentation , je nage complet . Ca devient frustrant. Je comprend le principe de fonctionnement ( à force de le lire tu m'étonnes ^^ ) , mais la mise en application sur le ws , je ne vois vraiment pas comment l'écrire . Je ne trouve aucun exemple configuration , d'agencement et d'interaction avec le ws .

---* Prend un flingue et se tire une balle *---

Ca m'énerve un peu xD . C'est vraiment la solution qui semble convenir et je ne suis pas capable de le faire.
27 Février 2007 08:21:15

En fait, un WS est juste une définition particulière de SOAP, en quelque sorte.

Normalement, la sécurité ne devrait pas faire parti de ton problème lorsque tu créés un WS.
Tu fais ton WS normalement, comme s'il n'y avait pas de sécurité du tout.
A ce point, tu as ton métier qui marche.

Une fois fait, au lieu de hoster ton WS sur le connecteur http, tu le places sur le connecteur https. De cette manière, ton WS bénéficiera du chiffrement SSL. Ton WS devient dès lors inviolable (théoriquement, bien sûr).
A ce point, tu as ton métier chiffré, mais en accès libre.

Par contre, étant donné que tout le monde, s'il possède le WSDL, pourra utiliser le WS, il faut en limiter l'accès. C'est là que l'on a besoin d'un service d'authentification.
Mon client possède un service kerberos pour remplir ce rôle, mais un simple md5 peut suffire. Par contre, il est judicieux de conserver le principe du token, car cela évite le spoofing.
Tu gardes donc la classe Token, mais le WS TrustMe peut utiliser une comparaison MD5 pour authentifier un utilisateur (comme unix/linux).
A ce point, tu as un accès finement contrôlé.

A partir du moment où tout le processus est encapsulé dans SSL, les mots de passes et les userID seront envoyés chiffrés.

Tu peux aussi utiliser un EJBSessionBean pour authentifier et traiter les WS métiers du client.
Lors de la création de la session, tu créés un EJB de session qui tient à jour l'état d'authentification de l'utilisateur. Tu peux stocker éventuellement son IP et un compteur de séquence pour plus de sécurité, mais cela n'est pas vraiment indispensable.
Si le client fait un appel WS métier alors qu'il n'est pas authentifié, tu renvois une exception.
Si le client utilises le WS TrustMe, tu acceptes l'authentification et tu mets à jour l'EJB de session ou tu lui renvois une exception en cas d'échec.

Je ne suis pas forcément très doué pour expliquer...

EDIT: Pour le protocole d'authentification kerberos, je dispose d'un assembly (dll) maison développé par mon client en .NET.
Chez mes clients bancaires, j'ai souvnt utilisé la comparaison MD5 des credentials.
27 Février 2007 09:33:32

Citation :

Une fois fait, au lieu de hoster ton WS sur le connecteur http, tu le places sur le connecteur https. De cette manière, ton WS bénéficiera du chiffrement SSL. Ton WS devient dès lors inviolable (théoriquement, bien sûr).


Donc je crée un couloir crypté , mais n'importe qui peut passer par ce couloir .
Si je veux restreindre un peu plus l'accès , utiliser des certificats serait possible en plus ? Est-ce vraiment utilise de rajouter cette barrière en plus
ou alors je me contente du Ws trustMe qui va se connecter sur une db pour vérifier l'identité du gars .

Citation :

Mon client possède un service kerberos pour remplir ce rôle, mais un simple md5 peut suffire.


Ah donc kerberos se trouve dans la partie client et non ws .
Je me trompe peut etre , mais c'est bien du made in $soft ce protocole ?
Je vais me contenter d'un simple md5 alors pour crypter les 2 paramètres .

Citation :

Tu peux aussi utiliser un EJBSessionBean pour authentifier et traiter les WS métiers du client.


J'avoue n'avoir jamais utilisé de EJB, donc c'est pour moi le moment d'apprendre une nouvelle chose de plus^^.

Citation :

Je ne suis pas forcément très doué pour expliquer...

Ca c'est toi qui le dit xD , on voit très bien que tu maitrises le sujet , c'est moi qui suit partit dans la mauvaise direction.

Je te remercie en tout cas pour les explications , c'est de plus en plus clair dans ma tête ( enfin reste les EJB à voir leur fonctionnement mais ca sur devellopez.net c'est assez devellopé , je ne devrais pas avoir de mal ).

Y a quand même une chose qui me frappe , IDN n'est pas entre "" le forum des developper , mais bizarrement il n'y a qu'ici que j'ai eu une réponse , et surtout expliquée avec précision.

27 Février 2007 10:12:45

Citation :
Si je veux restreindre un peu plus l'accès , utiliser des certificats serait possible en plus ? Est-ce vraiment utilise de rajouter cette barrière en plus
ou alors je me contente du Ws trustMe qui va se connecter sur une db pour vérifier l'identité du gars .

Un certificat serveur, tu en auras forcément un pour le connecteur SSL.
Des certificats clients, je te le déconseille car tu risques d'en avoir beaucoup et leur gestion va être périlleuse.
Le WS TrustMe, tu le mets aussi sur le connecteur SSL. De cette manière, lorsqu'un client tente une authentification, le userID et le mot de passe sera chiffré.
Sur le serveur, une simple comparaison md5 des userID et mots de passe est suffisante. Mais même pas nécessaire.
En fait, si tu ne veux pas stocker en base des mots de passe en clair, stocke les md5. Puis dans le WS TrustMe, tu compares les md5.
Mais si stocker en base des mots de passe en clair n'est pas un problème, alors t'embête même pas avec le md5.
De toutes façons, le seul fait d'utiliser le WS sur le connecteur SSL suffit à assurer la confidentialité de la liaison client/serveur.

Citation :
Ah donc kerberos se trouve dans la partie client et non ws.

Kerberos est un protocole d'authentification client/serveur.
Chaque partie en possède un bout. Le client et le serveur.
Ceci dit, c'est probablement complexe pour un besoin traditionnel.

Citation :
Je me trompe peut etre , mais c'est bien du made in $soft ce protocole ?

C'est un protocole RFC-***. Utilisé en premier sur unix.
Microsoft l'a utilisé pour l'authentification à partir de NT3.51.

Citation :
J'avoue n'avoir jamais utilisé de EJB, donc c'est pour moi le moment d'apprendre une nouvelle chose de plus^^.

Je t'ai parlé de l'EJB de Session car tu m'a dis que tu te trouves dans un conteneur J2EE (JOnAS).
L'EJB de session va juste t'aider à maintenir, côté serveur, l'état de la session de travail avec le client. En gros, est-il authentifié ?
Cet aspect est non obligatoire.
Si tu maintiens un EJB de Session, tu n'auras plus besoin de faire passer le Token à chaque appel WS métier pour prouver que tu es authentifié. Le serveur le saura en interrogeant l'EJB de session.
Si tu n'as pas l'EJB de session, il faudra que lors de chaque appel WS métier, tu fasses passer le Token.
27 Février 2007 10:23:41

Citation :
Le principe du ssl je l'avais compris , le hic c'est que je n'ai pas réussi à le mettre en pratique

Tu utilises JOnAS avec Apache ou avec Jetty ?
Dans les 2 cas, tu as un fichier de configuration qui décrit le connecteur dans lequel déployer les modules web.
Ce connecteur indique notamment le protocole réseau (http/https) et le port de connection.
Place tes WS en https sur le port 443.
Normalement, tu dois avoir 2 connecteurs. Le premier http/80 (celui par défaut) et le second https/443 en commentaires.
Il te suffit de décommenter le second et d'y placer tes WS.
27 Février 2007 10:41:30

Citation :
Sur le serveur, une simple comparaison md5 des userID et mots de passe est suffisante. Mais même pas nécessaire.
En fait, si tu ne veux pas stocker en base des mots de passe en clair, stocke les md5. Puis dans le WS TrustMe, tu compares les md5.
Mais si stocker en base des mots de passe en clair n'est pas un problème, alors t'embête même pas avec le md5.
De toutes façons, le seul fait d'utiliser le WS sur le connecteur SSL suffit à assurer la confidentialité de la liaison client/serveur.


Je viens d'en discuter un peu avec l'équipe , et on est arrivé à la même conclusion.

Les mots de passe et les droits d'utilisation sont stockés dans une db tout en clair. De plus pour les applications clientes en Power Builder , c'est pas impossible d'utiliser md5 , mais c'est pas ce qu'il ya de plus simple non plus ( rien de tel que java xD ) .


Citation :
Tu utilises JOnAS avec Apache ou avec Jetty ?

Avec Apache.
Je vais regarder de suite à le configurer sur ma machine.

Voila qui est fait , j'ai modifié ce que tu m'as dit dans le server.xml

Citation :

Un certificat serveur, tu en auras forcément un pour le connecteur SSL.


Je dois donc en générer un avec keytool ? Il y a un endroit dans un fichier de conf dans lequel je dois le référencer ?
Ou bien tout cela se fait automatiquement ?
Citation :

Le WS TrustMe, tu le mets aussi sur le connecteur SSL.

La par contre je ne vois pas trop ce que tu veux dire par le mettre sur le connecteur.

Je n'ai pas eu de formation sur la configuration de jonas ( en fait rien sur les web Services mdr ) et celui qui s'occupe de la config du serveur de production est au Brésil , ca n'aide pas mdr .

27 Février 2007 10:58:02

Citation :
Les mots de passe et les droits d'utilisation sont stockés dans une db tout en clair. De plus pour les applications clientes en Power Builder , c'est pas impossible d'utiliser md5 , mais c'est pas ce qu'il ya de plus simple non plus ( rien de tel que java xD ) .

Tu peux quand même stocker les mots de passe en md5.
Ton WS TrustMe envoi le mot de passe en clair mais dans le tunnel SSL.
C'est ton WS qui va le transformer en md5 et le comparer à celui stocké en base.
Cela évite le select * from XXX dans la table des users pour faire afficher les mots de passe en clair de tout le monde.
27 Février 2007 10:59:01

Ah ben , c'est bien ce qu'il me semblait , au démarrage de Jonas , j'ai un beau message d'acceuil ^^

  1. 2007-02-27 10:57:19,610 : Http11BaseProtocol.init : Error initializing endpoint
  2. java.io.FileNotFoundException: C:\Documents and Settings\vanackerd\.keystore (Le fichier spécifié est introuvable)
  3. at java.io.FileInputStream.open(Native Method)
  4. at java.io.FileInputStream.<init>(FileInputStream.java:106)


Donc il faut bien que j'en génère une . Ce qui est fait , maintenant je vais chercher où je lui indique lequel utiliser.
27 Février 2007 11:27:01

Citation :
La par contre je ne vois pas trop ce que tu veux dire par le mettre sur le connecteur.

Le détail de comment on fait pour JOnAS+Apache, je demanderai à Optionnelle lorsqu'elle reviendra cet après-midi.

Le principe général est le suivant :
Tu ouvres un "connecteur" http et/ou https dans le fichier de configuration. Normalement, chaque connecteur possède un identifiant.
Ensuites, tu indiques pour chaque war déployé quel connecteur utiliser (probablement dans un autre fichier de conf). Si tu ne précises rien, il va utiliser celui par défaut ou le premier déclaré (cela dépend des implémentations des Applications Serveurs).
27 Février 2007 12:31:02

Au fait je viens de remarquer quelque chose .

Citation :

public Token TrustMe(String userID, String pwd); // WS d'authentification


Le token génère une exception et du coup le deploy ne s'effectue pas.

Citation :

2007-02-27 12:30:08,176 : EngineConfigurationFactoryServlet.getServerEngineConfig : Unable to find config file. Creating new servlet engine config file: /WEB-INF/server-config.wsdd
2007-02-27 12:30:08,739 : WSDDService.deployTypeMapping : Unable to deploy typemapping: {http://DefaultNamespace}Token
java.lang.ClassNotFoundException: DefaultNamespace.Token_Type


27 Février 2007 14:57:10

Citation :

Je suppose que tu as lu ça : http://jonas.objectweb.org/current [...] figuration


Oui et souvent c'est la même page qui revient constamment .

Pour la configuration du serveur jonas , j'ai envoyé un mail au gars qui s'occupe de ca chez nous ,la réponse je ne l'aurais certainement pas dans la semaine , mais ce n'est qu'un détail pour après .

Par contre le token je n'arrive toujours pas à le déployer même en le simplifiant au minimum .

Le fait de retourner le même type que la classe , il n'a pas l'air d'apprécier , de plus quand je génère le wsdl ( qui n'aboutit pas ) , le plug in sous eclipse m'informe déjà que ce n'est pas dans les normes .


27 Février 2007 21:29:35

Je crois qu'en java, si tu veux retourner un objet complexe (une classe par exemple), tu dois t'assurer que l'objet soit sérialisable.
Peut-être devrais-tu implémenter une interface Serializable ou quelque-chose du même genre.

Sinon, tu peux conserver l'instance Token côté serveur dans une Hashtable.
Tu fais un md5 de l'instance Token, tu la stocke dans une Hashtable avec le md5 comme clé.
Puis, tu retournes la clé (le md5) au client. Comme ça, cela te fait retourner un type simple.

Ensuite, tu balades le md5 du Token dans tes appels WS métiers.

PS: Désolé, c'est ma femme qui est experte J2EE et elle est à la maternité en vu d'une césarienne demain !
28 Février 2007 07:52:54

Oui le problème venait bien du retour d'un objet de type complexe , j'ai réglé mon problème en fin d'après midi et j'ai su implémenter tout ce que tu m'as expliqué . J'ai enfin quelque chose qui tourne convenablement ^^.

Je te remercie pour cette assistance très utile .


Et félicitations pour cet heureux évènements ;) 
Tom's guide dans le monde
  • Allemagne
  • Italie
  • Irlande
  • Royaume Uni
  • Etats Unis
Suivre Tom's Guide
Inscrivez-vous à la Newsletter
  • ajouter à twitter
  • ajouter à facebook
  • ajouter un flux RSS