Tout ça JAAS

Avez-vous déjà eu besoin de créer un mécanisme d'authentification de connexion pour une application? Les chances sont, vous l'avez fait, et probablement plus d'une fois, que chaque nouvelle implémentation soit proche, mais pas identique, de la précédente. Par exemple, une implémentation peut utiliser une base de données Oracle, une autre peut utiliser une authentification NT et une autre, un annuaire LDAP (protocole d'annuaire d'accès léger). Ne serait-il pas agréable de prendre en charge tous ces mécanismes de sécurité sans changer de code au niveau de l'application?

Désormais dans le monde Java, vous pouvez le faire avec le service d'authentification et d'autorisation Java (JAAS). Cette API relativement nouvelle était une extension de J2SE (Java 2 Platform, Standard Edition) 1.3, est une API principale de J2SE 1.4 et fait également partie de la spécification J2EE (Java 2 Platform, Enterprise Edition) 1.3. Dans cet article, nous allons vous apprendre les bases de JAAS et vous montrer comment appliquer efficacement JAAS à des applications du monde réel. Nous avons basé l'application de cet article sur nos propres expériences d'intégration de JAAS dans un système Web Java existant qui utilisait un SGBDR (système de gestion de base de données relationnelle) pour stocker les informations de connexion des utilisateurs. Avec JAAS, nous avons conçu des mécanismes de connexion et d'authentification plus robustes, flexibles et cohérents.

Vous pouvez télécharger un ensemble complet d'exemples de travail à partir des ressources ci-dessous (comprend les sources Java, les JSP (JavaServer Pages), la configuration JAAS, avec la base de données et les scripts de construction). Nous avons testé ces exemples en utilisant le serveur Resin avec JDBC (Java Database Connectivity) et la base de données MySQL.

Authentification et autorisation Java: vue d'ensemble

Avant JAAS, le modèle de sécurité de Java était principalement façonné par son origine en tant que langage indépendant de la plate-forme pour les applications distribuées en réseau. À ses débuts, Java apparaissait souvent sous forme de code mobile, comme des applets basées sur un navigateur, et par conséquent, le modèle de sécurité initial se concentrait sur la protection des utilisateurs en fonction de l'origine du code et de son créateur. Les premiers mécanismes de sécurité Java tels que SecurityManagers, le concept de sandbox, la signature de code et les fichiers de stratégie étaient tous destinés à protéger les utilisateurs du système.

L'invention de JAAS reflète l'évolution de Java vers un langage de programmation polyvalent, utilisé pour implémenter des applications client et serveur traditionnelles qui nécessitent une connexion et un contrôle d'accès. JAAS protège le système des utilisateurs en autorisant ou en refusant l'accès en fonction de qui ou de quoi exécute le programme. Bien que JAAS puisse effectuer à la fois l'authentification et l'autorisation, dans cet article, nous nous concentrons principalement sur l'authentification.

JAAS peut simplifier votre développement de la sécurité Java en mettant une couche d'abstraction entre votre application et les mécanismes d'authentification et d'autorisation sous-jacents disparates. Cette indépendance vis-à-vis des plates-formes et des algorithmes vous permet d'utiliser différents mécanismes de sécurité sans modifier votre code au niveau de l'application. Comme avec la plupart des API de sécurité Java, JAAS atteint cette indépendance d'implémentation grâce à un cadre extensible d'interfaces de fournisseur de services (SPI) enfichables: un ensemble de classes abstraites et d'interfaces pour lesquelles des implémentations spécifiques sont développées.

La figure 1 ci-dessous donne un aperçu de haut niveau de la manière dont JAAS réalise cette connectivité. Votre code de couche application traite principalement d'un fichier LoginContext. En dessous se LoginContexttrouve un ensemble d'un ou plusieurs LoginModules configurés dynamiquement , qui gèrent l'authentification réelle à l'aide de l'infrastructure de sécurité appropriée.

JAAS fournit des LoginModuleimplémentations de référence , telles que JndiLoginModule; vous pouvez également développer le vôtre, comme nous le ferons ici avec le RdbmsLoginModule. Nous vous montrerons également comment configurer rapidement une application avec un choix d'implémentations à l'aide d'un simple fichier de configuration.

En plus d'être enfichable, JAAS est empilable: dans le cadre d'une seule connexion, un ensemble de modules de sécurité peuvent s'empiler les uns sur les autres, chacun appelé dans l'ordre et interagissant chacun avec une infrastructure de sécurité différente.

Les aspects JAAS sont calqués sur certains modèles d'architecture de sécurité familiers et sur des cadres existants. La fonctionnalité empilable, par exemple, ressemble délibérément au framework Unix Pluggable Authentication Module (PAM). D'un point de vue transactionnel, JAAS adopte des comportements similaires aux protocoles de validation en deux phases (2PC). Les concepts de configuration de sécurité de JAAS, y compris les Policyfichiers et Permissions, proviennent des packages de sécurité J2SE 1.2. JAAS emprunte également des idées à d'autres cadres de sécurité établis, tels que les certificats X.509, dont le nom Subjectest dérivé (vous en apprendrez plus plus Subjecttard).

Remarque: JAAS n'est que l'une des nombreuses nouvelles API de sécurité Java. Pour plus d'informations sur la sécurité Java, consultez la barre latérale «Le puzzle de la sécurité Java» et les ressources ci-dessous.

JAAS côté client et serveur

Vous pouvez appliquer JAAS sur le client et le serveur. Son utilisation côté client est simple, comme nous le démontrerons bientôt. Du côté du serveur, les choses deviennent un peu plus complexes. Actuellement, JAAS sur le marché des serveurs d'applications est un peu incohérent; Les serveurs d'applications J2EE utilisent JAAS légèrement différemment, selon celui que vous utilisez. Par exemple, JBossSX, en utilisant sa propre architecture, intègre bien JAAS dans son cadre de sécurité global (qui est détaillé dans l'excellent article JavaWorld de Scott Stark "Integrate Security Infrastructures with JBossSX" (août 2001)). Cependant, bien que WebLogic 6.x prenne en charge JAAS, les détails diffèrent.

Pour que vous puissiez comprendre JAAS à la fois du côté serveur et du côté client, nous allons montrer des exemples des deux dans cet article. Et pour des raisons de simplicité sur le serveur, nous utiliserons le serveur d'applications Resin afin que nous puissions commencer avec une ardoise plus propre (Resin a son propre schéma d'authentification enfichable, mais il n'est pas standard, donc l'utilisation de JAAS nous donne plus de portabilité options plus tard).

Core JAAS

Pour démarrer avec JAAS, vous devez d'abord vous assurer qu'il est installé. J2SE 1.4 inclut déjà JAAS; J2SE 1.3 ne le fait pas. Si vous souhaitez continuer à utiliser J2SE 1.3, téléchargez JAAS à partir de Sun Microsystems. Une fois que vous avez téléchargé et installé JAAS dans un répertoire donné, vous verrez un sous-répertoire appelé lib, qui contient un fichier nommé jaas.jar. Vous devrez ajouter ce fichier à votre chemin de classe ou le copier dans votre répertoire d'extensions JRE (Java Runtime Environment) (dans \lib\ext, où est l'emplacement de votre JRE). Vous êtes alors prêt pour JAAS. Remarque: si vous utilisez un serveur d'applications, il peut déjà inclure JAAS. Consultez la documentation de votre serveur pour plus de détails.

Avec l'une de ces approches, notez que vous pouvez modifier certains des paramètres de propriété système liés à JAAS (ainsi que de nombreux autres paramètres de sécurité Java) dans le fichier de propriétés de sécurité Java. Ce fichier,, java.securityest situé dans le /lib/securityrépertoire et écrit au format de fichier de propriétés Java standard.

L'utilisation de l'authentification JAAS à partir de votre application implique généralement les étapes suivantes:

  1. Créer un LoginContext
  2. Passez éventuellement un CallbackHandlerà la LoginContextpour collecter ou traiter les données d'authentification
  3. Effectuer l' authentification en appelant la LoginContextde » login()méthode
  4. Effectuer des actions privilégiées en utilisant le renvoyé Subject(en supposant que la connexion réussisse)

Voici un exemple minimal:

LoginContext lc = nouveau LoginContext ("MonExemple"); essayez {lc.login (); } catch (LoginException) {// L'authentification a échoué. } // Authentification réussie, nous pouvons maintenant continuer. // Nous pouvons utiliser le sujet renvoyé si nous le voulons. Sujet sub = lc.getSubject (); Subject.doAs (sous, nouveau MyPrivilegedAction ());

Sous les couvertures, quelques autres choses se produisent:

  1. Lors de l'initialisation, le LoginContexttrouve l'entrée de configuration "MyExample"dans un fichier de configuration JAAS (que vous avez configuré) pour déterminer les LoginModules à charger (voir Figure 2)
  2. Lors de la connexion, l' LoginContextappelle chaque LoginModulede » login()méthode
  3. Chaque login()méthode effectue l'authentification ou inscrit unCallbackHandler
  4. Le CallbackHandlerutilise un ou plusieurs Callbacks pour interagir avec l'utilisateur et recueillir des entrées
  5. A new Subject instance is populated with authentication details such as Principals and credentials

We'll explain further details below, but to begin, let's look at the key JAAS classes and interfaces involved in the process. These are typically divided into the following three groups:

Table 1. JAAS classes and interfaces

Common Subject, Principal, credential (credential is not any specific class, but can be any object)
Authentication LoginContext, LoginModule, CallbackHandler, Callback
Authorization Policy, AuthPermission, PrivateCredentialPermission

Most of these classes and interfaces are in the javax.security.auth package's subpackages, with some prebuilt implementations in the com.sun.security.auth package, included only in J2SE 1.4.

Note: Because we focus on authentication in this article, we don't delve into the authorization classes.

Common: Subjects, Principals, and Credentials

The Subject class represents an authenticated entity: an end-user or administrator, or a Web service, device, or another process. The class contains three sets of security information types:

  • Identities: In the form of one or more Principals
  • Public credentials: Such as name or public keys
  • Private credentials: Like passwords or private keys

Principals represent Subject identities. They implement the java.security.Principal interface (which predates JAAS) and java.io.Serializable. A Subject's most important method is getName(), which returns an identity's string name. Since a Subject instance contains an array of Principals, it can thus have multiple names. Because a social security number, login ID, email address, and so on, can all represent one user, multiple identities prove common in the real world.

The last element here, credential, is not a class or an interface, but can be any object. Credentials can include any authentication artifact, such as a ticket, key, or password, that specific security systems might require. The Subject class maintains unique Sets of private and public credentials, which can be retrieved with methods such as getPrivateCredentials() and getPublicCrendentials(). These methods are more often used by security subsystems than at the application layer.

Authentication: LoginContext

Your application layer uses LoginContext as its primary class for authenticating Subjects. LoginContext also represents where JAAS's dynamic pluggability comes into play, because when you construct a LoginContext, you specify a named configuration to load. The LoginContext typically loads the configuration information from a text file, which in turn tells the LoginContext which LoginModules to use during login.

The three commonly used methods in LoginContext are:

Table 2. LoginContext methods

login() Performs login, a relatively complex step that invokes all LoginModules specified for this configuration. If it succeeds, it creates an authenticated Subject. If it fails, it throws a LoginException.
getSubject() Returns the authenticated Subject.
logout() Logs out the authenticated Subject and removes its Principals and credentials.

We will show how to use these methods later.

Authentication: LoginModule

LoginModule is the interface to specific authentication mechanisms. J2SE 1.4 ships with a set of ready-to-use LoginModules, including:

Table 3. LoginModules in J2SE 1.4

JndiLoginModule Verifies against a directory service configured under JNDI (Java Naming and Directory Interface)
Krb5LoginModule Authenticates using Kerberos protocols
NTLoginModule Uses the current user's NT security information to authenticate
UnixLoginModule Uses the current user's Unix security information to authenticate

Along with these modules comes a set of corresponding concrete Principal implementations in the com.sun.security.auth package, such as NTDomainPrincipal and UnixPrincipal.

The LoginModule interface has five methods:

Table 4. LoginModule methods

initialize() Called after the LoginModule is constructed.
login() Performs the authentication.
commit() Called by the LoginContext after it has accepted the results from all LoginModules defined for this application. We assign Principals and credentials to the Subject here.
abort() Called when any LoginModule for this application fails (even though earlier ones in sequence may have succeeded—thus akin to a 2PC model). No Principals or credentials are assigned to the Subject.
logout() Removes the Principals and credentials associated with the Subject.

The application layer calls none of these methods directly—the LoginContext invokes them as needed. Our example below will elaborate on these methods' implementations.

Authentication: CallbackHandlers and Callbacks

CallbackHandlers et Callbacks permettent à un de LoginModulerecueillir les informations d'authentification nécessaires auprès d'un utilisateur ou d'un système, tout en restant indépendant du mécanisme d'interaction réel. Nous exploiterons cette capacité dans notre conception - RdbmsLoginModulecela ne dépend pas de la façon dont les informations d'identification de l'utilisateur (nom d'utilisateur / mot de passe) sont obtenues et peuvent donc être utilisées dans les différents environnements d'application que nous illustrerons (soit à partir de la ligne de commande, soit à partir d'une JSP) .