All das JAAS
Mussten Sie jemals einen Anmeldeauthentifizierungsmechanismus für eine Anwendung erstellen? Die Chancen stehen gut und wahrscheinlich mehr als einmal, wobei jede neue Implementierung der vorherigen nahe kommt, aber nicht mit dieser identisch ist. Beispielsweise kann eine Implementierung eine Oracle-Datenbank verwenden, eine andere eine NT-Authentifizierung und eine andere ein LDAP-Verzeichnis (Lightweight Access Directory Protocol). Wäre es nicht schön, all diese Sicherheitsmechanismen zu unterstützen, ohne den Code auf Anwendungsebene zu ändern?
Jetzt in der Java-Welt können Sie mit dem Java Authentication and Authorization Service (JAAS). Diese relativ neue API war eine Erweiterung in J2SE (Java 2 Platform, Standard Edition) 1.3, ist eine Kern-API in J2SE 1.4 und Teil der J2EE (Java 2 Platform, Enterprise Edition) 1.3-Spezifikation. In diesem Artikel lernen Sie die Grundlagen von JAAS kennen und zeigen Ihnen, wie Sie JAAS effektiv auf reale Anwendungen anwenden können. Wir haben die Anwendung dieses Artikels auf unseren eigenen Erfahrungen mit der Integration von JAAS in ein vorhandenes webbasiertes Java-System basiert, das ein RDBMS (relationales Datenbankverwaltungssystem) zum Speichern von Benutzeranmeldeinformationen verwendet. Mit JAAS haben wir robustere, flexiblere und konsistentere Anmelde- und Authentifizierungsmechanismen entwickelt.
Sie können einen vollständigen Satz von Arbeitsbeispielen aus den folgenden Ressourcen herunterladen (einschließlich Java-Quellen, JSPs (JavaServer Pages), JAAS-Konfiguration mit Datenbank- und Build-Skripten). Wir haben diese Beispiele mit dem Resin-Server mit JDBC (Java Database Connectivity) und der MySQL-Datenbank getestet.
Java-Authentifizierung und -Autorisierung: Das große Ganze
Vor JAAS war das Sicherheitsmodell von Java hauptsächlich von seiner Entstehung als plattformunabhängige Sprache für verteilte, vernetzte Anwendungen geprägt. In den Anfängen wurde Java häufig als mobiler Code angezeigt, z. B. als browserbasierte Applets. Daher konzentrierte sich das ursprüngliche Sicherheitsmodell auf den Schutz der Benutzer basierend darauf, woher der Code stammt und wer ihn erstellt hat. Frühe Java-Sicherheitsmechanismen wie SecurityManager
s, das Sandbox-Konzept, die Codesignatur und Richtliniendateien sollten Benutzer vor dem System schützen.
Die Erfindung von JAAS spiegelt Javas Entwicklung zu einer universellen Programmiersprache wider, die zur Implementierung traditioneller Client- und Serveranwendungen verwendet wird, die Anmeldung und Zugriffskontrolle erfordern. JAAS schützt das System vor Benutzern, indem der Zugriff basierend darauf, wer oder was das Programm ausführt, zugelassen oder verweigert wird . Während JAAS sowohl Authentifizierung als auch Autorisierung durchführen kann, konzentrieren wir uns in diesem Artikel hauptsächlich auf die Authentifizierung.
JAAS kann Ihre Java-Sicherheitsentwicklung vereinfachen, indem eine Abstraktionsschicht zwischen Ihrer Anwendung und unterschiedlichen zugrunde liegenden Authentifizierungs- und Autorisierungsmechanismen eingefügt wird. Diese Unabhängigkeit von Plattformen und Algorithmen ermöglicht es Ihnen, verschiedene Sicherheitsmechanismen zu verwenden, ohne den Code auf Anwendungsebene zu ändern. Wie bei den meisten Java-Sicherheits-APIs erreicht JAAS diese Implementierungsunabhängigkeit durch ein erweiterbares Framework aus steckbaren Service Provider-Schnittstellen (SPIs): eine Reihe abstrakter Klassen und Schnittstellen, für die bestimmte Implementierungen entwickelt werden.
Abbildung 1 unten gibt einen allgemeinen Überblick darüber, wie JAAS diese Steckbarkeit erreicht. Ihr Code auf Anwendungsebene befasst sich hauptsächlich mit a LoginContext
. Darunter LoginContext
befindet sich ein Satz von einem oder mehreren dynamisch konfigurierten LoginModule
s, die die eigentliche Authentifizierung unter Verwendung der entsprechenden Sicherheitsinfrastruktur durchführen.
JAAS bietet einige Referenzimplementierungen LoginModule
, wie z JndiLoginModule
. Sie können auch Ihre eigenen entwickeln, wie wir es hier mit dem tun RdbmsLoginModule
. Wir zeigen auch, wie Sie mithilfe einer einfachen Konfigurationsdatei schnell eine Anwendung mit einer Auswahl von Implementierungen einrichten können.
JAAS ist nicht nur steckbar, sondern auch stapelbar: Im Rahmen einer einzelnen Anmeldung können mehrere Sicherheitsmodule übereinander gestapelt werden, die jeweils nacheinander aufgerufen werden und mit einer anderen Sicherheitsinfrastruktur interagieren.
JAAS-Aspekte basieren auf einigen bekannten Sicherheitsarchitekturmustern und vorhandenen Frameworks. Die stapelbare Funktion ähnelt beispielsweise bewusst dem PAM-Framework (Unix Pluggable Authentication Module). Aus transaktionaler Sicht nimmt JAAS Verhaltensweisen an, die den 2PC-Protokollen (Two-Phase Commit) ähneln. Die Sicherheitskonfigurationskonzepte von JAAS, einschließlich Policy
Dateien und Permissions
, stammen aus den J2SE 1.2-Sicherheitspaketen. JAAS leiht sich auch Ideen aus anderen etablierten Sicherheits-Frameworks aus, z. B. X.509-Zertifikaten, von denen der Name Subject
abgeleitet ist (mehr dazu Subject
später).
Hinweis: JAAS ist nur eine von mehreren neuen Java-Sicherheits-APIs. Weitere Informationen zur Java-Sicherheit finden Sie in der Seitenleiste "Das Java-Sicherheitspuzzle" und in den Ressourcen unten.
Client- und serverseitiges JAAS
Sie können JAAS sowohl auf dem Client als auch auf dem Server anwenden. Die Verwendung auf der Client-Seite ist unkompliziert, wie wir in Kürze demonstrieren werden. Auf der Serverseite werden die Dinge etwas komplexer. Derzeit ist JAAS auf dem Anwendungsservermarkt etwas inkonsistent. J2EE-App-Server verwenden JAAS etwas anders, je nachdem, welchen Sie verwenden. Zum Beispiel integriert JBossSX mithilfe seiner eigenen Architektur JAAS gut in sein Gesamtsicherheitsframework (das in Scott Starks ausgezeichnetem JavaWorld- Artikel "Integrieren von Sicherheitsinfrastrukturen in JBossSX" (August 2001) beschrieben wird). Obwohl WebLogic 6.x JAAS unterstützt, unterscheiden sich die Details.
Damit Sie JAAS sowohl aus server- als auch aus clientseitiger Perspektive verstehen können, werden in diesem Artikel Beispiele für beides vorgestellt. Der Einfachheit halber verwenden wir den Resin-Anwendungsserver, damit wir mit einem saubereren Slate beginnen können (Resin verfügt zwar über ein eigenes steckbares Authentifizierungsschema, ist jedoch nicht standardisiert, sodass die Verwendung von JAAS uns mehr Portabilität bietet Optionen später).
Kern JAAS
Um mit JAAS zu beginnen, müssen Sie zunächst sicherstellen, dass es installiert ist. J2SE 1.4 enthält bereits JAAS; J2SE 1.3 nicht. Wenn Sie J2SE 1.3 weiterhin verwenden möchten, laden Sie JAAS von Sun Microsystems herunter. Sobald Sie JAAS heruntergeladen und in einem bestimmten Verzeichnis installiert haben, wird ein Unterverzeichnis mit dem Namen angezeigt lib
, das eine Datei mit dem Namen enthält jaas.jar
. Sie müssen diese Datei zu Ihrem Klassenpfad hinzufügen oder in Ihr JRE-Erweiterungsverzeichnis (Java Runtime Environment) kopieren (in \lib\ext
, wo sich der Speicherort Ihrer JRE befindet). Sie sind dann JAAS-fähig. Hinweis: Wenn Sie einen Anwendungsserver verwenden, enthält dieser möglicherweise bereits JAAS. Überprüfen Sie die Dokumentation Ihres Servers auf Details.
Beachten Sie, dass Sie bei jedem dieser Ansätze einige der JAAS-bezogenen Systemeigenschaftseinstellungen (sowie viele andere Java-Sicherheitseinstellungen) in der Java-Sicherheitseigenschaftendatei ändern können. Diese Datei java.security
befindet sich im /lib/security
Verzeichnis und ist im Standarddateiformat für Java-Eigenschaften geschrieben.
Die Verwendung der JAAS-Authentifizierung in Ihrer Anwendung umfasst normalerweise die folgenden Schritte:
- Ein ... kreieren
LoginContext
- Übergeben Sie optional a
CallbackHandler
anLoginContext
, um Authentifizierungsdaten zu sammeln oder zu verarbeiten - Führen Sie die Authentifizierung durch den Aufruf
LoginContext
‚slogin()
Methode - Führen Sie privilegierte Aktionen mit dem zurückgegebenen aus
Subject
(vorausgesetzt, die Anmeldung ist erfolgreich).
Hier ist ein minimales Beispiel:
LoginContext lc = neuer LoginContext ("MyExample"); try {lc.login (); } catch (LoginException) {// Authentifizierung fehlgeschlagen. } // Authentifizierung erfolgreich, wir können jetzt fortfahren. // Wir können den zurückgegebenen Betreff verwenden, wenn wir möchten. Betreff sub = lc.getSubject (); Subject.doAs (sub, new MyPrivilegedAction ());
Unter der Decke treten noch einige andere Dinge auf:
- Während der Initialisierung
LoginContext
findet der Konfigurationseintrag"MyExample"
in einer JAAS-Konfigurationsdatei (die Sie konfiguriert haben), um zu bestimmen, welcheLoginModule
s geladen werden sollen (siehe Abbildung 2). - Während der Anmeldung
LoginContext
ruft jederLoginModule
dielogin()
Methode auf - Jede
login()
Methode führt die Authentifizierung durch oder schreibt a einCallbackHandler
- Der
CallbackHandler
verwendet ein oder mehrereCallback
s, um mit dem Benutzer zu interagieren und Eingaben zu sammeln - A new
Subject
instance is populated with authentication details such asPrincipal
s 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
Principal
s - Public credentials: Such as name or public keys
- Private credentials: Like passwords or private keys
Principal
s 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 Principal
s, 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 Set
s 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 Subject
s. 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 LoginModule
s 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 LoginModule s 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 Principal s 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. |
|
Performs the authentication. |
commit() |
Called by the LoginContext after it has accepted the results from all LoginModule s defined for this application. We assign Principal s 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 Principal s or credentials are assigned to the Subject . |
logout() |
Removes the Principal s 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
CallbackHandler
Mit s und Callback
s kann LoginModule
ein Benutzer die erforderlichen Authentifizierungsinformationen von einem Benutzer oder System sammeln und dabei unabhängig vom tatsächlichen Interaktionsmechanismus bleiben. Wir werden diese Fähigkeit in unserem Design nutzen - unsere RdbmsLoginModule
hängt nicht davon ab, wie die Benutzeranmeldeinformationen (Benutzername / Passwort) abgerufen werden, und kann daher in den verschiedenen Anwendungsumgebungen verwendet werden, die wir veranschaulichen werden (entweder über die Befehlszeile oder über eine JSP). .