Angepassten JASPI-Authentifizierungsprovider entwickeln
Sie können einen angepassten JASPI-Authentifizierungsprovider (Java™ Authentication SPI for Containers) entwickeln, indem Sie Klassen erstellen, die die erforderlichen Schnittstellen implementieren, die in der Spezifikation JSR 196 (Java Authentication Service Provider Interface for Containers) beschrieben sind.
Vorbereitende Schritte
Sehen Sie sich die speziellen Voraussetzungen für die Schnittstellenimplementierung für JASPI-Authentifizierungsprovider und -Module in der Spezifikation JSR 196 (Java Authentication Service Provider Interface for Containers) an.
Informationen zu diesem Vorgang
WebSphere Application Server unterstützt die Verwendung von Authentifizierungsprovidern anderer Anbieter, die mit dem Servlet-Containerprofil kompatibel sind, das in Java Authentication SPI for Containers (JASPI) Version 1.1 spezifiziert ist.
Das Servlet-Containerprofil definiert Schnittstellen, die von der Sicherheitslaufzeitumgebung zusammen mit dem Web-Container in WebSphere Application Server verwendet werden, um Authentifizierungsmodule vor und nach der Verarbeitung einer Webanforderung in einer Anwendung aufzurufen. Eine Authentifizierung mit JASPI-Modulen wird nur durchgeführt, wenn JASPI in der Sicherheitskonfiguration aktiviert wurde und wenn dem Webmodul ein konfigurierter JASPI-Provider zugeordnet wurde, der die empfangene Webanforderung verarbeitet.
Zum Entwickeln eines angepassten Authentifizierungsproviders erstellen Sie Klassen, die die erforderlichen Schnittstellen implementieren, die in der Spezifikation JSR 196 (Java Authentication Service Provider Interface for Containers) beschrieben sind. Ein Provider kann für die Authentifizierung ein oder mehrere Authentifizierungsmodule verwenden. Module können Callbacks für die Durchführung der Authentifizierung verwenden, oder sie können die erforderlichen Benutzeridentitätsinformationen dem Clientsubjekt manuell hinzufügen. Ja nach Umfang des Providers können die Implementierungsklassen an verschiedenen Positionen im Anwendungsserver gespeichert werden.
Vorgehensweise
- Erstellen Sie eine Klasse, die die Schnittstelle "javax.security.auth.message.config.AuthConfigProvider" implementiert. Die Klasse "AuthConfigProvider" muss einen öffentlichen Konstruktor mit zwei Argumenten und die öffentliche (oder allgemein zugängliche) Methode "getServerAuthConfig" definieren:
import java.util.Map; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.message.AuthException; import javax.security.auth.message.config.AuthConfigFactory; import javax.security.auth.message.config.AuthConfigProvider; import javax.security.auth.message.config.ServerAuthConfig; public class SampleAuthConfigProvider implements AuthConfigProvider { public SampleAuthConfigProvider(Map<String, String> properties, AuthConfigFactory factory) { ... } public ServerAuthConfig getServerAuthConfig(String layer, String appContext, CallbackHandler handler) throws AuthException { ... } }
WebSphere Application Server verwendet eine Instanz der Implementierungsklasse "AuthConfigProvider", wenn eine Anforderung eingeht, die vom Webmodul der Anwendung verarbeitet werden muss. Die Methode "getServerAuthConfig" wird verwendet, um eine Instanz von "ServerAuthConfig" abzurufen. Das Argument "CallbackHandler" im Methodenaufruf wird von den Authentifizierungsmodulen verwendet.
- Erstellen Sie eine Klasse, die die Schnittstelle "javax.security.auth.message.config.ServerAuthConfig" implementiert. Die Klasse "ServerAuthConfig" muss die öffentlichen Methoden "getAuthContextID" und "getAuthContext" definieren:
import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.config.ServerAuthConfig; import javax.security.auth.message.config.ServerAuthContext; public class SampleServerAuthConfig implements ServerAuthConfig { public String getAuthContextID(MessageInfo messageInfo) throws IllegalArgumentException { ... } public ServerAuthContext getAuthContext(String authContextID, Subject serviceSubject, Map properties) throws AuthException { ... } }
Die Methoden "getAuthContextID" und "getAuthContext" in der Implementierungsklasse "ServerAuthConfig" werden verwendet, um eine Instanz von "ServerAuthContext" abzurufen.
- Erstellen Sie eine Klasse, die die Schnittstelle "javax.security.auth.message.config.ServerAuthContext" implementiert. Die Implementierungsklasse "ServerAuthContext" muss die öffentlichen Methoden "validateRequest" und "secureResponse" definieren:
import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.config.ServerAuthContext; public class SampleServerAuthContext implements ServerAuthContext { public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { ... } public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { ... } }
Die Methode "validateRequest" in der Implementierungsklasse "ServerAuthContext" wird verwendet, um das Modul aufzurufen, das die empfangene Webanforderungsnachricht authentifiziert. Wenn das Authentifizierungsergebnis positiv ist, teilt der Web-Container die empfangene Webanforderungsnachricht zu, die vom Zielwebmodul in der Anwendung verarbeitet wird. Sollte das Authentifizierungsergebnis negativ sein, wird die Anforderung mit dem entsprechenden Antwortstatus zurückgewiesen.
- Erstellen Sie eine Klasse, die die Schnittstelle "javax.security.auth.message.module.ServerAuthModule" implementiert. Die Implementierungsklasse "ServerAuthModule" muss die öffentlichen Methoden "initialize", "validateRequest" und "secureResponse" definieren:
import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.security.auth.message.MessagePolicy; import javax.security.auth.message.module.ServerAuthModule; public class SampleAuthModule implements ServerAuthModule { public void initialize(MessagePolicy requestPolicy, MessagePolicy responsePolicy, CallbackHandler handler, Map options) throws AuthException { ... } public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { ... } public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException { ... } }
Die Methode initialize in der Implementierungsklasse "ServerAuthModule" wird von der Implementierungsklasse "ServerAuthContext" aufgerufen, um das Authentifizierungsmodul zu initialisieren und dieses der Instanz von "ServerAuthContext" zuzuordnen.
Die Methoden "validateRequest" und "secureResponse" in dieser Klasse werden verwendet, um die javax.servlet.http.HttpServletRequest bzw. die javax.servlet.http.HttpServletResponse in der empfangenen javax.security.auth.message.MessageInfo zu verarbeiten. Diese Methoden können die CallbackHandler-Instanz, die in der Methode initialize empfangen wurde, verwenden, um mit der WebSphere-Sicherheitslaufzeitumgebung hinsichtlich der Validierung eines Benutzerkennworts und mit der aktiven Benutzerregistry hinsichtlich des Abrufs einer eindeutigen ID und der Zugehörigkeitsgruppen für einen Benutzer zu interagieren. Die abgerufenen Daten werden in eine Hashtabelle in die Gruppe der privaten Berechtigungsnachweise im Clientsubjekt kopiert. Die CallbackHandler-Implementierung von WebSphere Application Server unterstützt drei Callbacks:- CallerPrincipalCallback
- GroupPrincipalCallback
- PasswordValidationCallback
Wenn CallbackHandler vom Authentifizierungsmodul nicht verwendet wird und validateRequest einen Erfolgsstatus zurückgibt, erfordert WebSphere Application Server, dass eine Hashtable-Instanz mit den Benutzeridentitätsinformationen in das Clientsubjekt eingeschlossen wird, so dass eine angepasste Anmeldung durchgeführt werden kann, um die Berechtigungsnachweise für den Benutzer abzurufen. Diese Hashtable-Instanz kann dem Clientsubjekt, wie im folgenden Beispiel gezeigt, hinzugefügt werden:import java.util.Hashtable; import java.util.String; import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import com.ibm.wsspi.security.registry.RegistryHelper; import com.ibm.wsspi.security.token.AttributeNameConstants.AttributeNameConstants; public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { ... UserRegistry reg = RegistryHelper.getUserRegistry(null); String uniqueid = reg.getUniqueUserID(username); Hashtable hashtable = new Hashtable(); hashtable.put(AttributeNameConstants.WSCREDENTIAL_UNIQUEID, uniqueid); hashtable.put(AttributeNameConstants.WSCREDENTIAL_SECURITYNAME, username); hashtable.put(AttributeNameConstants.WSCREDENTIAL_PASSWORD, password); hashtable.put(AttributeNameConstants.WSCREDENTIAL_GROUPS, groupList); //optional clientSubject.getPrivateCredentials().add(hashtable); ... }
Weitere Informationen zu den Hashtable-Voraussetzungen und zur angepassten Anmeldung finden Sie im Artikel "Angepasste Anmeldemodule für eine Systemanmeldekonfiguration für JAAS entwickeln".
Zur Unterstützung der Authentifizierungsmethode der Spezifikation Java Servlet 3.0 muss der Methode validateRequest in der Implementierungsklasse ServerAuthModule die folgende Logik hinzugefügt werden:import java.util.Map; import javax.security.auth.Subject; import javax.security.auth.message.AuthException; import javax.security.auth.message.AuthStatus; import javax.security.auth.message.MessageInfo; import javax.servlet.http.HttpServletRequest; public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException { ... Map msgMap = messageInfo.getMap(); if ("authenticate".equalsIgnoreCase(msgMap.get("com.ibm.websphere.jaspi.request"))) { // diese Anforderung bezieht sich auf die Authentifizierungsmethode String authHeader = ((HttpServletRequest) messageInfo.getRequestMessage()).getHeader("Authorization"); if (authHeader == null) { // Der Benutzer hat noch keinen Benutzernamen und kein Kennwort angegeben, // AuthStatus.SEND_CONTINUE zurückgeben, um die Informationen anzufordern } else { // Authentifizierung mit dem Benutzernamen und dem Kennwort im Authentifizierungsheader durchführen } } else { // Dies ist keine Authentifizierungsanforderung gemäß Servlet 3.0. Wie gewöhnlich verarbeiten } ... }
- Kompilieren Sie alle neu erstellten Klassen. Die folgenden JAR-Dateien in Ihrer Installation von WebSphere Application Server müssen im Klassenpfad angegeben werden, damit die neuen Klassen erfolgreich kompiliert werden:
- Stammverzeichnis_des_Anwendungsservers/dev/JavaEE/j2ee.jar
- Stammverzeichnis_des_Anwendungsservers/dev/was_public.jar (falls öffentliche WebSphere-APIs verwendet wurden)
- Erstellen Sie eine JAR-Datei mit den kompilierten Klassen. Je nach Anforderungen kann die JAR-Datei an eine von drei Positionen kopiert werden:
- Stammverzeichnis_des_Anwendungsservers/lib
Diese Position ist immer im Klassenpfad für das Klassenladeprogramm von WebSphere Application Server enthalten. Wenn Sie diese Position verwenden, kann der Provider für eine Gruppe von Webmodulen oder Anwendungen, Standardprovider der Zelle oder Domäne für alle Webmodule und Anwendungen und manuell als permanenter Provider registriert werden.
- Gemeinsam genutzte Bibliothek
Kopieren Sie die JAR-Datei des Providers an eine beliebige Position im System von WebSphere Application Server. Konfigurieren Sie eine gemeinsam genutzte Bibliothek, die auf die JAR-Datei zeigt, und fügen Sie diese gemeinsam genutzte Bibliothek dem Anwendungs- bzw. Serverklassenpfad hinzu. In einer gemeinsam genutzten Bibliothek kann der Provider für eine Gruppe von Webmodulen oder Anwendungen registriert werden, aber der Provider kann nicht als Standardprovider für die Zelle oder Domäne verwendet werden. Er kann auch nicht als permanenter Provider registriert werden, weil die gemeinsam genutzte Bibliothek während des Serverstarts nicht im Klassenpfad für die Providerregistrierung enthalten ist. Weitere Informationen zum Konfigurieren einer gemeinsam genutzten Bibliothek finden Sie im Artikel "Gemeinsam genutzte Bibliotheken erstellen".
- Integration in die Anwendung
Schließen Sie die JAR-Datei des Providers in die EAR-Datei der Anwendung als Dienstprogramm-JAR ein, oder integrieren Sie die kompilierten Klassendateien in die WAR-Datei des Webmoduls. Der integrierte Provider kann für die Webmodule in der Anwendung registriert werden, solange die Klassen im Klassenpfad für das Webmodul enthalten sind. Dieser Provider kann weder als Standardprovider der Zelle oder Domäne verwendet, noch als permanenter Provider registriert werden. Die Klassen in der Anwendung stehen während der Serverstarts nicht für die Providerregistrierung zur Verfügung.
- Stammverzeichnis_des_Anwendungsservers/lib
- Konfigurieren Sie den Provider mithilfe der Administrationskonsole oder mithilfe eines Verwaltungsscripts in der Sicherheitskonfiguration.
Weitere Informationen finden Sie im Artikel Neuen JASPI-Authentifizierungsprovider über die Administrationskonsole konfigurieren bzw. im Artikel Befehlsgruppe "JaspiManagement" für das Objekt "AdminTask".


http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=tsec_jaspi_develop
Dateiname:tsec_jaspi_develop.html