Tutto quel JAAS

Hai mai avuto bisogno di creare un meccanismo di autenticazione del login per un'applicazione? Le probabilità sono, e probabilmente più di una volta, con ogni nuova implementazione simile, ma non identica, a quella precedente. Ad esempio, un'implementazione potrebbe utilizzare un database Oracle, un'altra potrebbe utilizzare un'autenticazione NT e un'altra, una directory LDAP (protocollo di directory di accesso leggero). Non sarebbe bello supportare tutti questi meccanismi di sicurezza senza modificare alcun codice a livello di applicazione?

Ora, nel mondo Java, puoi farlo con Java Authentication and Authorization Service (JAAS). Questa API relativamente nuova era un'estensione in J2SE (Java 2 Platform, Standard Edition) 1.3, è un'API principale in J2SE 1.4 e fa anche parte della specifica J2EE (Java 2 Platform, Enterprise Edition) 1.3. In questo articolo, ti insegneremo gli elementi essenziali di JAAS e ti mostreremo come applicare efficacemente JAAS alle applicazioni del mondo reale. Abbiamo basato l'applicazione di questo articolo sulle nostre esperienze di integrazione di JAAS in un sistema Java Web esistente che utilizzava un RDBMS (sistema di gestione di database relazionali) per memorizzare le informazioni di accesso dell'utente. Con JAAS, abbiamo progettato meccanismi di accesso e autenticazione più robusti, flessibili e coerenti.

È possibile scaricare un set completo di esempi di lavoro dalle risorse seguenti (include sorgenti Java, JSP (JavaServer Pages), configurazione JAAS, con database e script di build). Abbiamo testato questi esempi utilizzando il server Resin con JDBC (Java Database Connectivity) e il database MySQL.

Autenticazione e autorizzazione Java: il quadro generale

Prima di JAAS, il modello di sicurezza di Java era principalmente modellato dalla sua origine come linguaggio indipendente dalla piattaforma per applicazioni distribuite in rete. All'inizio, Java appariva spesso come codice mobile, come applet basate su browser, e quindi il modello di sicurezza iniziale si concentrava sulla protezione degli utenti in base all'origine del codice e a chi lo creava. I primi meccanismi di sicurezza Java come SecurityManagers, il concetto di sandbox, la firma del codice e i file dei criteri erano tutti concepiti per proteggere gli utenti dal sistema.

L'invenzione di JAAS riflette l'evoluzione di Java in un linguaggio di programmazione generico, utilizzato per l'implementazione di applicazioni client e server tradizionali che richiedono login e controllo degli accessi. JAAS protegge il sistema dagli utenti consentendo o negando l'accesso in base a chi o cosa esegue il programma. Sebbene JAAS possa eseguire sia l'autenticazione che l'autorizzazione, in questo articolo ci concentriamo principalmente sull'autenticazione.

JAAS può semplificare lo sviluppo della sicurezza Java inserendo un livello di astrazione tra l'applicazione e diversi meccanismi di autenticazione e autorizzazione sottostanti. Questa indipendenza dalle piattaforme e dagli algoritmi consente di utilizzare diversi meccanismi di sicurezza senza modificare il codice a livello di applicazione. Come con la maggior parte delle API di sicurezza Java, JAAS raggiunge questa indipendenza dall'implementazione attraverso un framework estensibile di SPI (pluggable service provider interfaces): un insieme di classi astratte e interfacce su cui vengono sviluppate implementazioni specifiche.

La Figura 1 di seguito offre una panoramica di alto livello di come JAAS ottiene questa collegabilità. Il codice a livello di applicazione si occupa principalmente di un file LoginContext. Sotto LoginContextc'è un insieme di uno o più configurati dinamicamente LoginModule, che gestiscono l'autenticazione effettiva utilizzando l'infrastruttura di sicurezza appropriata.

JAAS fornisce alcune LoginModuleimplementazioni di riferimento , come il JndiLoginModule; puoi anche svilupparne uno tuo, come faremo qui con il RdbmsLoginModule. Mostreremo anche come configurare rapidamente un'applicazione con una scelta di implementazioni utilizzando un semplice file di configurazione.

Oltre ad essere collegabile, JAAS è impilabile: nel contesto di un singolo login, una serie di moduli di sicurezza possono essere impilati uno sull'altro, ciascuno chiamato in ordine e ciascuno interagendo con una diversa infrastruttura di sicurezza.

Gli aspetti JAAS sono modellati su alcuni modelli architetturali di sicurezza familiari e framework esistenti. La funzione stackable, ad esempio, assomiglia deliberatamente al framework Unix Pluggable Authentication Module (PAM). Da un punto di vista transazionale, JAAS adotta comportamenti simili ai protocolli di commit a due fasi (2PC). I concetti di configurazione della sicurezza di JAAS, inclusi i Policyfile e Permissions, provengono dai pacchetti di sicurezza J2SE 1.2. JAAS prende anche in prestito idee da altri framework di sicurezza consolidati, come i certificati X.509, da cui Subjectderiva il nome (ne saprai di più in Subjectseguito).

Nota: JAAS è solo una delle numerose nuove API di sicurezza Java. Per ulteriori informazioni sulla sicurezza Java, vedere la barra laterale "The Java Security Puzzle" e le risorse di seguito.

JAAS lato client e lato server

È possibile applicare JAAS sia sul client che sul server. Usarlo sul lato client è semplice, come dimostreremo a breve. Sul lato server le cose diventano un po 'più complesse. Attualmente, JAAS nel mercato dei server delle applicazioni è un po 'incoerente; I server delle app J2EE utilizzano JAAS in modo leggermente diverso, a seconda di quale si utilizza. Ad esempio, JBossSX, utilizzando la propria architettura, integra perfettamente JAAS nel suo framework di sicurezza generale (che è descritto in dettaglio nell'eccellente articolo di JavaWorld di Scott Stark "Integrate Security Infrastructures with JBossSX" (agosto 2001)). Tuttavia, sebbene WebLogic 6.x supporti JAAS, i dettagli differiscono.

In modo che tu possa comprendere JAAS sia dal punto di vista del lato server che del lato client, mostreremo esempi di entrambi in questo articolo. E per motivi di semplicità sul server, utilizzeremo il server delle applicazioni Resin in modo da poter iniziare con una lavagna più pulita (Resin ha uno schema di autenticazione collegabile, ma non è standard, quindi l'uso di JAAS ci offre una maggiore portabilità opzioni successive).

Core JAAS

Per iniziare con JAAS, devi prima assicurarti che sia installato. J2SE 1.4 include già JAAS; J2SE 1.3 non lo fa. Se si desidera continuare a utilizzare J2SE 1.3, scaricare JAAS da Sun Microsystems. Una volta scaricato e installato JAAS in una determinata directory, vedrai una sottodirectory chiamata lib, che contiene un file denominato jaas.jar. Dovrai aggiungere questo file al tuo classpath o copiarlo nella directory delle estensioni JRE (Java Runtime Environment) (in \lib\ext, dov'è la posizione del tuo JRE). Allora sei pronto per JAAS. Nota: se si utilizza un server delle applicazioni, potrebbe già includere JAAS. Controlla la documentazione del tuo server per i dettagli.

Con uno qualsiasi di questi approcci, notare che è possibile modificare alcune delle impostazioni delle proprietà di sistema relative a JAAS (oltre a molte altre impostazioni di sicurezza Java) nel file delle proprietà di sicurezza Java. Questo file,, java.securitysi trova nella /lib/securitydirectory e viene scritto nel formato file delle proprietà Java standard.

L'utilizzo dell'autenticazione JAAS dall'applicazione in genere comporta i seguenti passaggi:

  1. Creare un LoginContext
  2. Facoltativamente, passare a CallbackHandlera LoginContext, per raccogliere o elaborare i dati di autenticazione
  3. Eseguire l'autenticazione chiamando il LoginContext's login()metodo
  4. Eseguire azioni privilegiate utilizzando il restituito Subject(supponendo che l'accesso abbia esito positivo)

Ecco un esempio minimo:

LoginContext lc = new LoginContext ("MyExample"); prova {lc.login (); } catch (LoginException) {// Autenticazione non riuscita. } // Autenticazione riuscita, ora possiamo continuare. // Possiamo usare il Soggetto restituito se vogliamo. Oggetto sub = lc.getSubject (); Subject.doAs (sub, new MyPrivilegedAction ());

Sotto le copertine, si verificano alcune altre cose:

  1. Durante l'inizializzazione, LoginContexttrova la voce di configurazione "MyExample"in un file di configurazione JAAS (che hai configurato) per determinare quali messaggi LoginModulecaricare (vedi Figura 2)
  2. Durante login, la LoginContextchiama ogni LoginModule's login()metodo
  3. Ciascun login()metodo esegue l'autenticazione o inserisce un fileCallbackHandler
  4. Le CallbackHandlerutilizza uno o più Callbacks di interagire con l'utente e raccogliere ingresso
  5. Una nuova Subjectistanza viene popolata con dettagli di autenticazione come se Principalcredenziali

Spiegheremo ulteriori dettagli di seguito, ma per iniziare, esaminiamo le classi e le interfacce JAAS chiave coinvolte nel processo. Questi sono generalmente suddivisi nei seguenti tre gruppi:

Tabella 1. Classi e interfacce JAAS

Comune Subject, Principal, Credenziali (credenziali non è una classe specifica, ma può essere qualsiasi oggetto)
Autenticazione LoginContext, LoginModule, CallbackHandler,Callback
Autorizzazione Policy, AuthPermission,PrivateCredentialPermission

La maggior parte di queste classi e interfacce si trovano nei javax.security.authsottopacchetti del pacchetto, con alcune implementazioni predefinite nel com.sun.security.authpacchetto, incluse solo in J2SE 1.4.

Nota: poiché in questo articolo ci concentriamo sull'autenticazione, non approfondiamo le classi di autorizzazione.

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 e Callbacks consentono a un utente di LoginModuleraccogliere le informazioni di autenticazione necessarie da un utente o sistema, pur rimanendo indipendenti dal meccanismo di interazione effettivo. Sfrutteremo questa capacità nel nostro progetto: la nostra RdbmsLoginModulenon dipende da come vengono ottenute le credenziali dell'utente (nome utente / password) e possono quindi essere utilizzate nei diversi ambienti applicativi che illustreremo (dalla riga di comando o da un JSP) .