Sécurité J2EE: conteneur versus personnalisé

Depuis la première fois qu'une page de connexion a été ajoutée à une application Web, la sécurité a toujours été l'un des éléments clés essentiels au succès des applications sur le Web. Historiquement, tout était codé à la main. Chaque application Web disposait d'une méthode personnalisée d'authentification et d'autorisation des utilisateurs. Les développeurs ont également intégré des composants pour l'enregistrement, l'administration et toute autre fonction nécessaire. Bien qu'un peu de frais généraux, cette approche a permis une grande flexibilité.

Avec l'avènement de JAAS, le service d'authentification et d'autorisation Java, les applications ont obtenu un ensemble d'interfaces et une configuration qu'elles pouvaient utiliser pour standardiser ces tâches. Même avec l'ajout de JAAS à la spécification, J2EE a encore quelques problèmes à résoudre avant que les développeurs d'applications ne puissent arrêter de créer des API personnalisées. Choisir entre utiliser les normes J2EE ou créer une solution personnalisée nécessite de connaître les compromis de chacun et, bien sûr, les exigences de votre application.

Cet article vise à fournir toutes les informations nécessaires pour décider entre la sécurité personnalisée ou la sécurité des conteneurs. Je discute des fonctions de sécurité des applications les plus courantes pour fournir les informations nécessaires sur la sécurité. À la suite de cette discussion, vous trouverez une explication détaillée des implémentations de sécurité J2EE fournies par les spécifications ainsi que des méthodes les plus courantes d'implémentation de la sécurité personnalisée. Une fois que vous aurez mieux compris chacune des méthodes, vous devriez disposer de suffisamment d'informations pour choisir la méthode qui répond le mieux aux exigences de votre application.

Qu'est-ce qu'un conteneur?

Avant de discuter des différents types de sécurité et des problèmes de mise en œuvre de la sécurité, examinons ce qu'est un conteneurest. Un conteneur est un environnement dans lequel une application s'exécute. Il est également synonyme de serveur d'applications J2EE. En termes de conteneurs J2EE, une application J2EE s'exécute à l'intérieur du conteneur, qui a des responsabilités spécifiques par rapport à l'application. Il existe de nombreux types de conteneurs J2EE et différents niveaux de prise en charge J2EE. Tomcat d'Apache est un conteneur Web qui implémente uniquement les parties Servlet (application Web) de la spécification J2EE. Le WebLogic de BEA est un serveur d'applications J2EE entièrement conforme, ce qui signifie qu'il prend en charge tous les aspects de la spécification J2EE et a réussi les tests de certification J2EE de Sun. Si vous n'êtes pas sûr du support fourni par votre serveur d'applications, contactez le fournisseur pour plus d'informations.

Sécurité des applications

Un autre sujet que nous devons aborder avant de commencer est la distinction entre la sécurité des applications et les autres types de sécurité. La sécurité des applications est la sécurité effectuée directement par une application ou indirectement par un framework ou un conteneur pour une application par rapport aux utilisateurs de cette application. Un exemple d'utilisateur d'application est une personne qui se connecte à une librairie en ligne et achète quelques livres Java. D'autres types de sécurité existent, tels que la sécurité du réseau et la sécurité JVM. Un exemple de ces types de sécurité est l'utilisateur qui démarre un processus Java sur une machine. Dans le reste de cet article, chaque fois que je parle de sécurité, je parle de sécurité des applications. Les autres types de sécurité sortent du cadre de cette discussion.

L'accent est mis ici spécifiquement sur la sécurité J2EE, qui est un type de sécurité d'application car elle traite les utilisateurs d'une application J2EE (c'est-à-dire les appelants). Un utilisateur peut être une personne utilisant la librairie en ligne ou une autre application qui utilise les services d'achat de l'application de la librairie, comme un autre revendeur en ligne.

Fonctions de sécurité des applications

Il existe cinq fonctions principales lorsque l'on considère la sécurité des applications: l'authentification, l'autorisation, l'enregistrement, la maintenance du compte (mises à jour) et la suppression / désactivation du compte. Bien que seul un petit sous-ensemble de toutes les fonctions possibles d'une application, ce sont les plus fondamentales et les plus standard pour toutes les applications. Moins formellement, ces fonctions sont la connaissance de l'utilisateur (authentification), la connaissance de ce que l'utilisateur peut faire (autorisation), la création de nouveaux utilisateurs (enregistrement), la mise à jour des informations utilisateur (gestion du compte) et la suppression d'un utilisateur ou l'empêchement d'un utilisateur d'accéder à l'application. (suppression de compte).

La plupart des applications permettent à l'utilisateur ou à un administrateur d'exécuter ces fonctions. Lorsque les utilisateurs exécutent ces fonctions, ils le font pour eux-mêmes. Les administrateurs exécutent toujours ces fonctions pour le compte d'autres utilisateurs.

Comme cela sera illustré, toutes ces fonctions ne peuvent pas être accomplies sans une solution personnalisée, même pour l'authentification. Nous allons passer brièvement en revue chacun d'eux pour illustrer davantage les concepts et ce qui manque à J2EE qui doit être construit sur mesure.

Authentification

L'authentification est le processus d'identification d'un utilisateur interagissant avec une application. Au moment d'écrire ces lignes, l'authentification J2EE pouvait être mise en œuvre en utilisant une variété de solutions, chacune définie dans le cadre de la spécification J2EE (version 1.0-1.4). L'authentification est le concept principal de cette discussion et sera abordée plus en détail ultérieurement. Il est important de réaliser que l'authentification est la fonction de sécurité la plus prise en charge dans la spécification J2EE, mais un code ou une configuration personnalisé est généralement requis pour implémenter l'authentification J2EE (également appelée authentification de conteneur).

Autorisation

L'autorisation est le processus de vérification qu'un utilisateur est autorisé à effectuer une action spécifique. J2EE couvre ce sujet, mais il est limité à l'autorisation basée sur les rôles, ce qui signifie que l'activité peut être limitée en fonction des rôles attribués à l'utilisateur. Par exemple, les utilisateurs dans le rôle de gestionnaire peuvent être en mesure de supprimer l'inventaire, tandis que les utilisateurs dans le rôle d'employé peuvent pas.

En outre, les applications peuvent envisager deux types d'autorisation différents: Java Runtime Environment (JRE) / conteneur et autorisation d'application. L'autorisation JRE / conteneur est le processus permettant de déterminer si l'utilisateur qui fait la demande dispose des privilèges pour le faire. Le JRE / conteneur détermine cela avant l'exécution de tout code. Un exemple est un conteneur J2EE qui doit d'abord vérifier si l'utilisateur actuel dispose des autorisations pour exécuter un servlet (via une contrainte d'URL de ressource) avant d'exécuter le servlet. Ce type d'autorisation est également appelé sécurité déclarativecar il est déclaré dans les fichiers de configuration de l'application Web. À moins d'être prise en charge par le conteneur, la sécurité déclarative ne peut pas être modifiée au moment de l'exécution. La sécurité déclarative peut être utilisée de nombreuses manières pour autoriser les utilisateurs d'applications J2EE, mais ce sujet dépasse le cadre de cette discussion. (Voir le chapitre 12 de la spécification Servlet 2.3. La section 2 couvre la sécurité déclarative et 8 est un bon point de départ pour les contraintes de sécurité.)

Comme mentionné précédemment, l'utilisateur peut être une autre application ou simplement un utilisateur d'application. Dans tous les cas, l'autorisation JRE / conteneur est effectuée lors de chaque demande. Ces requêtes peuvent être des requêtes HTTP d'un navigateur vers une application Web ou des appels EJB (Enterprise JavaBeans) distants. Dans les deux cas, à condition que le JRE / conteneur connaisse l'utilisateur, il peut effectuer une autorisation en fonction des informations de cet utilisateur.

L'autorisation d'application est le processus d'autorisation pendant l'exécution de l'application. L'autorisation d'application peut en outre être décomposée en autorisations basées sur les rôles et basées sur les segments. Un exemple d'autorisation d'application basée sur les rôles est lorsqu'une application applique différents niveaux de majoration en fonction du fait qu'un utilisateur est un employé ou un visiteur (c'est-à-dire, une remise pour les employés). J2EE fournit des API appelées sécurité programmatique pour obtenir une autorisation basée sur les rôles (voir la spécification du servlet 2.3 Chapitre 12, Section 3 pour plus d'informations).

L'autorisation basée sur un segment est une autorisation basée sur d'autres attributs d'un utilisateur, tels que l'âge ou les loisirs. L'autorisation basée sur les segments est appelée telle parce qu'elle regroupe les utilisateurs en segments en fonction d'attributs spécifiques. J2EE n'a pas de méthode de mise en œuvre de l'autorisation basée sur les segments. Un exemple d'autorisation basée sur des segments est de savoir si un bouton sur un formulaire est visible par les utilisateurs de plus de 40 ans. Certains fournisseurs peuvent offrir ce type d'autorisation, mais cela garantirait le verrouillage du fournisseur dans tous les cas.

enregistrement

L'enregistrement est le processus d'ajout d'un nouvel utilisateur à l'application. Les utilisateurs de l'application peuvent être en mesure de créer de nouveaux comptes pour eux-mêmes ou l'application peut choisir de limiter cette activité aux administrateurs d'application. La spécification J2EE n'a pas d'API ou de configuration permettant aux applications d'ajouter de nouveaux utilisateurs; par conséquent, ce type de sécurité est toujours personnalisé. J2EE n'a pas la capacité de dire au conteneur qu'un nouvel utilisateur s'est enregistré et que ses informations doivent être persistantes et conservées pendant sa session.

Entretien

La maintenance du compte est le processus de modification des informations de compte, telles que les informations de contact, les connexions ou les mots de passe. La plupart des applications permettent aux utilisateurs d'applications, ainsi qu'aux administrateurs, d'effectuer la maintenance. La spécification J2EE manque également d'API ou de configuration pour la maintenance des comptes. Il manque un mécanisme pour informer le conteneur que les informations utilisateur ont changé.

Effacement

La suppression de compte est généralement limitée aux utilisateurs administratifs uniquement. En de rares occasions, certaines applications peuvent permettre aux utilisateurs de supprimer leurs propres comptes. En fait, la plupart des applications ne suppriment jamais les utilisateurs; ils désactivent simplement le compte afin que l'utilisateur ne puisse plus se connecter. Effectuer des suppressions forcées et rapides est généralement mal vu car les données du compte sont beaucoup plus difficiles à ressusciter si nécessaire. J2EE ne fournit aucun moyen de supprimer ou de désactiver les utilisateurs des applications. Il manque un mécanisme pour indiquer au conteneur qu'un utilisateur spécifique a été inactivé ou supprimé. J2EE manque également d'un mécanisme pour déconnecter immédiatement un utilisateur de l'application lorsque son compte a été supprimé.

Qu'est-ce que l'authentification des conteneurs?

L'authentification du conteneur est le processus consistant à indiquer au conteneur l'identité de l'utilisateur qui effectue la demande en cours. Pour la plupart des conteneurs, ce processus implique d'associer l' ServletRequestobjet actuel , le thread d'exécution actuel et une session interne à l'identité de l'utilisateur. En associant une session à l'identité, le conteneur peut garantir que la demande actuelle et toutes les demandes suivantes du même utilisateur peuvent être associées à la même session, jusqu'à ce que la session de cet utilisateur expire. Cet objet de session n'est généralement pas le même que l' HttpSessionobjet, bien que le premier soit utilisé pour créer et maintenir le second. Chaque demande ultérieure du même utilisateur est associée à la session à l'aide de la réécriture d'URL ou d'un cookie de session, conformément à la spécification Servlet 2.3, chapitre 7.

Comme mentionné ci-dessus dans notre discussion sur l'autorisation, chaque action que le conteneur prend ainsi que chaque action que JRE entreprend au nom de cet utilisateur sont soigneusement vérifiées pour s'assurer que l'utilisateur a l'autorisation d'exécuter l'action. Pour réitérer notre exemple précédent, lorsque le conteneur exécute un servlet au nom de l'utilisateur, il vérifie que l'utilisateur appartient à l'ensemble de rôles disposant des autorisations pour exécuter ce servlet. JRE 1.4 effectue également ces vérifications pour de nombreuses actions, y compris lorsqu'un fichier ou un socket s'ouvre. L'authentification JRE est un concept puissant et peut garantir que chaque demande adressée à un conteneur est essentiellement sûre.

Actuellement, J2EE fournit quelques mécanismes différents pour implémenter l'authentification des utilisateurs. Il s'agit notamment de l'authentification par formulaire, de l'authentification client HTTPS et de l'authentification de base HTTP. JAAS est inclus en tant que méthode d'authentification obligatoire que les conteneurs doivent prendre en charge. Mais la spécification n'est pas stricte sur la manière dont le conteneur doit fournir cette fonctionnalité; par conséquent, chaque conteneur fournit une prise en charge différente pour JAAS. En outre, JAAS en lui-même est un cadre d'authentification autonome et pourrait être utilisé pour implémenter l'authentification de conteneur, que la spécification la prenne en charge ou non. J'expliquerai ce concept plus en détail plus tard.

Chacun des mécanismes d'authentification fournit une manière standard de donner au conteneur des informations sur l'utilisateur. J'appelle cela la réalisation d'accréditation . Le conteneur doit toujours utiliser ces informations pour vérifier que l'utilisateur existe et dispose des autorisations suffisantes pour effectuer la demande. J'appelle cela l' authentification des informations d'identification . Certains conteneurs fournissent une configuration pour configurer l'authentification des informations d'identification et d'autres fournissent des interfaces qui doivent être implémentées.

Méthodes d'authentification J2EE

Examinons brièvement certaines des méthodes les plus courantes pour implémenter et configurer l'authentification de conteneur.

Authentification par formulaire

L'authentification par formulaire permet aux utilisateurs d'être identifiés et authentifiés auprès du serveur d'applications J2EE à l'aide de n'importe quel formulaire HTML. L'action de formulaire doit être j_security_checket deux paramètres de requête HTTP (champs de saisie de formulaire) doivent toujours être dans la requête, l'un appelé j_usernameet l'autre j_password,. À l'aide de l'authentification par formulaire, la réalisation des informations d'identification se produit lorsque le formulaire est soumis et que le nom d'utilisateur et le mot de passe sont envoyés au serveur.

Voici un exemple de page JSP (JavaServer Pages) qui utilise l'authentification par formulaire:

 Login Entrez votre nom d'utilisateur:

Tapez votre mot de passe: