Beispiel: IBM WebSphere-spezifische User-Registry
Inhalt:
Anlegen der Application
Anlegen des EJB-Projekts
Implementierung der UserRegistry
Aktivieren der Sicherheit
Universal Test Client aktivieren
Sicherheit im EJB-Projekt
Sicherheit im Web-Projekt
Sicherheit im Application Client-Projekt
Sicherheit in der Enterprise Application
Troubleshooting und Security-Tipps
Für weitergehende Infos empfehle ich das IBM-Redbook "WebSphere V6: Security Handbook":
http://www.redbooks.ibm.com/redpieces/pdfs/sg246316.pdf
Dieses Beispiel zeigt die von Hr. Dreher vorgestellte UserRegistry in einem konkreten
Beispiel, außerdem wird die J2EE-Security gezeigt.
Aufbau des Beispiels:
- Es gibt zwei Rollen in dieser Anwendung, "administrator" und "student" (ist in Teilen noch aus
dem letzten Semester, wo wir eine Lehrveranstaltungsbelegung programmierten)
- Die Benutzer werden in zwei Datenbanktabellen "ADMINISTRATOR" und "STUDENT"
abgelegt, die jeweils über die Spalten ID, NAME, LOGIN und PASSWORT verfügen.
- Auf die Tabelle "STUDENT" greift eine gleichnamige EJB zu, für die Validierung des Logins wird sie durch direkten
SQL-Zugriff gelesen.
- Eine Session-Bean im EJB-Projekt enthält Methoden auf die nur Studenten bzw. Administratoren zugreifen dürfen.
- Zum Test dienen eine Webanwendung und ein Application-Client. Bei beiden muss der User sich anmelden, die Anmeldeinformationen
werden bis zum EJB-Projekt weitergeben.
Hier gibt es das Beispiel zum Download: SecurityExport.zip
Anlegen der Application
Wir legen eine Enterprise Application namens "Security" mit einem EJB-Projekt, ein Webprojekt und einen
Application Client an.
Anlegen des EJB-Projekts
Es wird eine EntityBean "Student" im Package de.fhw.swtvertiefung.knauf.security
mit den Feldern
ID (java.lang.Integer
), NAME, LOGIN und PASSWORT (jeweils java.lang.String
) erzeugt.
Anschließend ein Datenbankmapping für die Bean erzeugen lassen (Rechtsklick auf Deployment Deskriptor):
Es wird ein Top-Down-Mapping für eine Datenbank namens "KnaufDB" erzeugt.
Eine simple Session-Bean "Secured" mit Remote Interface wird erzeugt.
Wir verpassen ihr drei Methoden forAdminOnly()
, forStudentOnly()
und forBoth()
,
die keine weitere Implementierung haben.
Implementierung der UserRegistry
Nachdem wir das Datenbankschema angelegt haben, können wir diesem Schema eine nicht-Bean-Tabelle "ADMINISTRATOR"
zufügen. Dazu Rechtsklick auf das Projekt und "New" -> "Other..." -> "Data" -> "Table Definition" wählen.
Wir geben als Tabellenname "Administrator" an, bei "Database/schema" klicken wir auf "Browse..." und klicken uns
zur Schema-Definition durch.
Wir fügen die Spalten zu. ID ist vom Typ INTEGER, die anderen drei sind VARCHAR der Länge 255. Name und Passwort
lassen NULL-Werte zu, nur LOGIN nicht.
Im nächsten Schritt wählen wir ID als Primary-Key-Spalte aus.
Foreign Keys haben wir nicht.
Damit haben wir die Datenbanktabelle erzeugt.
Jetzt die Implementation der UserRegistry, de.fhw.swtvertiefung.knauf.security.userregistry.KnaufUserRegistry
,
sowie die beiden Hilfsklassen de.fhw.swtvertiefung.knauf.security.userregistry.Administrator
und
de.fhw.swtvertiefung.knauf.security.userregistry.Student
zufügen.
Aktivieren der Sicherheit
Die folgenden Schritte unbedingt in einem eigenen Profile durchführen !
Auch auf einem Privat-PC können Fehler
im folgenden dazu führen dass das Default-Profil des WebSphere ruiniert wird, und nur durch eine komplette Neuinstallation
"repariert" werden kann.
Nach dem Erzeugen des Profils den Server starten und die Anwendung publizieren (beim Schritt "Add/Remove projects" im
Schritt 2 die Checkbox "Create tables and data sources" unbedingt aktivieren, damit unsere ADMINISTRATOR-Tabelle erzeugt
wird !).
In der Datenbank (im Beispiel: KnaufDB) müssen wir mittels CView in der Tabelle ADMINISTRATOR mindestens einen
Datensatz anlegen (im Beispiel: Login=TEST, Passwort=TEST). Dieser User wird im nächsten Schritt verwendet um
den WebSphere-Server zu starten und zu stoppen.
Jetzt müssen wir den Server für die UserRegistry vorbereiten.
- Im Profil-Verzeichnis ein Unterverzeichnis "classes" anlegen.
- In dieses Verzeichnis das Package mit den drei class-Dateien der UserRegistry-Implementierung kopieren
(so dass eine Unterverzeichnisstruktur "de\fhw\swtvertiefung\knauf\security\userregistry" entsteht).
- In das gleiche Verzeichnis auch die Datei "db2j.jar" (JDBC-Treiber für Cloudscape) aus dem WSAD-Installationsverzeichnis
(z.B. C:\Programme\IBM\Rational\SDP\6.0\runtimes\base_v6\cloudscape\lib) kopieren. Das ist nötig weil unsere
UserRegistry sonst keine Datenbankverbindung herstellen kann.
- Die Datei "bin\setupCmdLine.bat" bearbeiten und folgende Zeile ändern (fett der einzufügende Teil):
SET WAS_EXT_DIRS=%USER_INSTALL_ROOT%\classes;%JAVA_HOME%\lib;%WAS_HOME%\classes;
%WAS_HOME%\lib;%WAS_HOME%\installedChannels;%WAS_HOME%\lib\ext;%WAS_HOME%\web\help;
%ITP_LOC%\plugins\com.ibm.etools.ejbdeploy\runtime
Den Server starten und die Administrative Console aufrufen (entweder aus der Entwicklungsumgebung heraus
oder unter der URL https://localhost:9043/ibm/console/).
Wir gehen links im Baum zu "Sicherheit" -> "Globale Sicherheit" und wählen in den Fenster "globale Sicherheit"
erstmal die "Benutzerdefinierte Registry" ganz rechts.
In der Benutzerdefinierten Benutzer-Registry gehen wir direkt weiter zu den "Benutzerdefinierten Merkmalen".
Wir legen drei Werte an:
DBDRIVER: com.ibm.db2j.jdbc.DB2jDriver
DBURL: jdbc:db2j:KnaufDB
DBSCHEMA: APP
Den Namen des Schemas erfährt man wenn man die Datenbank mit CView öffnet.
Die Änderungen speichern.
Das Ergebnis sollte so aussehen:
Jetzt zurück zur Benutzerdefinierten Registry. Hier geben wir den Namen unserer Klasse ein, und tragen außerdem
die User-ID ein, die wir im letzten Schritt in die Tabelle ADMINISTRATOR eingegeben haben. Beim Klassennamen
geben wir unsere UserRegistry-Implementation (de.fhw.swtvertiefung.knauf.security.userregistry.KnaufUserRegistry
)
an.
Die Änderungen speichern.
Zurück in die globale Sicherheit. Jetzt können wir sie aktivieren. Dazu den Haken bei "Globale Sicherheit aktivieren"
setzen, und direkt den automatisch gesetzten Haken bei "Java-2-Sicherheit erzwingen" rauswerfen (der macht uns nur mehr
Arbeit). In der ComboBox "Aktive Benutzer-Registry" wählen wir die Benutzerdefinierte Benutzer-Registry aus.
Es erfolgt eine Validierung ob die UserRegistry den konfigurierten User auch validieren kann. Wenn hier Fehler auftreten
ist unser Server immerhin nicht unerreichbar kaputt. Hat unsere Benutzervalidierung geklappt, dann müssen wir nur noch
mehrfach auf "Speichern" klicken.
Ab diesem Zeitpunkt müssen wir in der "IBM Rational Development Platform" zwei Einstellungen ändern:
-Als "Server connection type and admin port" funktioniert "RMI" leider nicht mehr (hat bei mir zwar den
Server gestartet aber danach keine Verbindung hergestellt). Stattdessen: SOAP aktivieren.
-In der Kategorie "Security" muss der Haken "Security is enabled on this server" gesetzt werden,
und ein gültiger Username und Passwort müssen angegeben werden.
Jetzt können wir den Tipp aus Hr. Drehers Anleitung umsetzen, der die Konsolenausgabe des Servers auf die
RAD-Konsole umzuleitet.
Einzige Änderung zu diesem Tipp: der absolute Pfad zur Datei redeployFileTransfer.jacl muss angegeben werden,
da die nicht in unserem eigenen Profil liegt. Der Befehl sieht also so aus:
wsadmin -profile C:\Programme\IBM\Rational\SDP\6.0\runtimes\base_v6\bin\redeployFileTransfer.jacl
-lang jacl -c "fileTransferAuthenticationOn
<cellname> <nodename> <servername>" -user <username>
-password <password>
Falls ihr einen anderen Pfad verwendet muss der natürlich angepaßt werden.
Die Ausgabe eines erfolgreich verlaufenden Befehls sollte so aussehen:
WASX7209I: Mit Prozess "server1" auf Knoten NodeKnauf2 über SOAP-Connector verbunden.
Typ des Prozesses: UnManagedProcess
Uninstall filetransfer -cell CellKnauf2 -node NodeKnauf2 -server server1
ADMA5017I: Die Deinstallation von filetransfer wurde gestartet.
ADMA5011I: Die Bereinigung des temporären Verzeichnisses für die Anwendung filetransfer ist abgeschlossen.
ADMA5106I: Die Anwendung filetransfer wurde deinstalliert.
Install C:\Programme\IBM\Rational\SDP\6.0\runtimes\base_v6/systemApps/filetransferSecured.ear
-cell CellKnauf2 -node NodeKnauf2 -server server1 -appname filetransfer
-usedefaultbindings -nocreateMBeansForResources
ADMA5016I: Die Installation von filetransfer wurde gestartet.
ADMA5011I: Die Bereinigung des temporären Verzeichnisses für die Anwendung filetransfer ist abgeschlossen.
ADMA5013I: Die Anwendung filetransfer wurde installiert.
Die Werte für "<cellname>", "<nodename>" und "<servername>" finden wir an den
markierten Stellen im Profil:
Es kann sein dass beim Ausführen des Befehls folgende Fehlermeldung auftritt:
WASX7209I: Mit Prozess "server1" auf Knoten NodeKnauf2 über SOAP-Connector verbunden.
Typ des Prozesses: UnManagedProcess
Uninstall filetransfer -cell CellKnauf2 -node NodeKnauf2 -server server1
Operation FAILED!
com.ibm.ws.scripting.ScriptingException: WASX7280E: Es ist keine Anwendung mit dem Namen "filetransfer" vorhanden.
Das bedeutet dass diese Änderung bereits durchgeführt wurde. In diesem Fall kann man sie mit folgendem
Befehl rückgängig machen:
wsadmin -profile C:\Programme\IBM\Rational\SDP\6.0\runtimes\base_v6\bin\redeployFileTransfer.jacl
-lang jacl -c "fileTransferAuthenticationOff
<cellname> <nodename> <servername>" -user <username>
-password <password>
Jetzt kann man einen neuen Installations-Versuch wagen.
Hinweis: manchmal scheint es länger zu dauern bis RAD die Konsolenausgabe umgeleitet hat,
oder bis er erkannt hat dass der Server gestartet ist. Keine Ahnung woran das liegt...
Universal Test Client aktivieren
Im Default bietet der Universal Test Client leider nur Lesezugriff auf das JNDI, d.h. der Test von Beans ist nicht möglich.
Kein Problem, wir tricksen ein bißchen:
In der Datei "properties\soap.client.props" im Profile suchen wir folgende Stelle:
#------------------------------------------------------------------------------
# SOAP Client Security Enablement
#
# - security enabled status ( false[default], true )
#------------------------------------------------------------------------------
com.ibm.SOAP.securityEnabled=false
com.ibm.SOAP.loginUserid=
com.ibm.SOAP.loginPassword=
Wir ändern die Werte so ab (einbauen unseres Standard-Users):
com.ibm.SOAP.securityEnabled=true
com.ibm.SOAP.loginUserid=TEST
com.ibm.SOAP.loginPassword=TEST
Nachdem wir den UTC aktiviert haben können wir auch Studenten in die Datenbank packen.
Sicherheit im EJB-Projekt
Im EJB-Projekt wollen wir einige Methoden der Session-Bean "Secured" absichern, so dass nur Benutzer in
spezifierten Rollen die Methoden aufrufen dürfen.
Dazu in den Deployment-Deskriptor von SecurityEJB wechseln und auf der Karteikarte "Assembly" zuerst die
"Security Roles" zufügen.
Die erste Rolle soll "administratorejb" heißen (den Namen können wir völlig frei wählen, das Mapping auf
echte Server-Gruppen/-Benutzer geschieht erst später.
Eine zweite Rolle "studentejb" zufügen.
Unter "Method Permissions" werden jetzt die Zugriffsrechte für diese Rollen vergeben. Wir fügen eine neue Methode
Permission zu und wählen im ersten Schritt die Rolle "administratorejb" aus.
Wir wählen die zu sichernde Bean aus, also "Secured".
Jetzt die Methoden forAdminOnly
und forBoth
auswählen, für die diese Zugriffsberechtigung gilt.
Das gleiche wiederholen für die Rolle "studentejb", die Zugriff auf forStudentOnly
und forBoth
bekommt.
Das Ergebnis sollte so aussehen:
Leider können wir das nicht im UTC testen da die Bean über keine Local Interfaces verfügt.
Sicherheit im Web-Projekt
Vorbereitung: Das Web-Projekt muss das EJB-Projekt referenzieren, eine EJB-Referenz auf die Bean "Secured"
muss angelegt werden.
Bevor wir hier die Sicherheit definieren legen wir zuerst drei JSP-Seiten an. "index.jsp" soll unsere
zugriffs-gesicherte Seite sein, "login.jsp" ist unser Login-Formular, und "errorpage.jsp" die Fehlerseite bei
Login-Fehlern.
"login.jsp" wird immer dann aufgerufen wenn ein noch nicht am Server authentifizierter User auf
eine gesicherte Seite zugreifen will.
Sie verwendet Form-Based Login, d.h. ein HTML-Formular wird zum User geschickt. Damit WebSphere die Informationen
aus diesem Anmeldeformular auswerten kann müssen Ziel-URL, Submit-Button sowie die Feldnamen für Login und Passwort wie folgt aussehen:
<form method="post" ACTION="j_security_check">
Login: <input type="text" name="j_username" /> <br>
Passwort: <input type="password" name="j_password" /> <br>
<input type="submit" name="login" value="Login">
</form>
"index.jsp" ruft zum Test die drei gesicherten Methoden der Secured-Bean auf. Außerdem gibt es dort einen Logout-Button.
Der muss in einem Formular stecken das so aussieht:
<FORM METHOD=POST ACTION="ibm_security_logout" NAME="logout">
Für sauberen Logout hier klicken: <br>
<input type="submit" name="logout" value="Logout">
<INPUT TYPE="HIDDEN" name="logoutExitPage" VALUE="login.jsp">
</FORM>
"logoutExitPage" gibt an auf welche Seite der User nach erfolgreichem Logout geleitet werden soll.
"errorpage.jsp" ist eine ganz normale Fehlerseite, ohne Besonderheiten.
Jetzt können wir uns der Security widmen. Im Web-Deployment-Deskriptor auf der Karteikarte "Security" zwei
Security Roles "administratorweb" und "studentweb" zufügen.
Unter "Security Constraints" werden Regeln definiert, welche Ressourcen von der Sicherheit betroffen sind.
Dazu eine neue zufügen und ihr einen aussagekräftigen Namen geben.
Im nächsten Schritt einen Resourcen-Namen (frei wählbar), die zu sichernden HTTP-Methoden und ein URL-Pattern
("/*") eingeben.
Jetzt müssen wir festlegen für welche Rollen diese Security Constraint gilt. Dazu auf der gleichen Karteikarte
die "Authorized Roles" festlegen (eine neue "Authorization Constraint" zugefügt).
Das Ergebnis sollte so aussehen:
Im letzten Schritt aktivieren wir den Form Based Login. Auf der Karteikarte "Pages" unter "Login"
wählen wir als "Authentication Method" "FORM", und geben die Login- und Fehler-Seiten unserer Anwendung an entsprechender
Stelle an.
Sicherheit im Application Client-Projekt
Vorbereitung: Das Application Client-Projekt muss das EJB-Projekt referenzieren, eine EJB-Referenz auf die Bean "Secured"
muss angelegt werden. Die Main Class muss auf de.fhw.swtvertiefung.knauf.security.SecurityClient
geändert werden.
In Sachen Security gibt es hier nichts zu konfigurieren, da der Application Client ja prinzipiell nicht im Server-Context läuft.
Sobald wir die Anwendung allerdings starten und auf eine gesicherte Methode der Bean zugreifen blendet die
Web-Sphere-Client-Schicht automatisch einen Login-Dialog ein !
Sicherheit in der Enterprise Application
Im Deployment Deskriptor der Enterprise Application schließlich legen wir fest welche der Rollen in den
Teilprojekten auf welche Nutzer oder Gruppen im Server gemappt werden.
Auf der Karteikarte "Security" auf "Gather..." klicken, dies sucht die in allen Deployment-Deskriptoren
definierten Rollen zusammen (es sollten hier jetzt vier Stück auftauchen). Jede der Rollen muss ausgewählt
werden. Unter "WebSphere Bindings" wird die Checkbox "Users/Groups" gesetzt und eine Gruppe zugefügt.
Für "administratorweb" und "administratorejb" heißt die Gruppe "administrator" (unter diesem Namen
wird sie von der UserRegistry zurückgegeben.
Für "studentweb" und "studentejb" heißt die Gruppe "student".
Das Ergebnis sieht so aus:
Jetzt endlich dürfen wir auf den Server deployen und können bei Application Client bzw. WebClient feststellen
wie sich Logins als Student bzw. Adminstrator auf die Methodenaufrufe der SecuredBean auswirken.
Ich habe die Erfahrung gemacht dass es nach dem Publish mit geänderten Security-Einstellungen in der Enterprise
Application am besten ist den Server neu zu starten !
Der Webclient ist zu erreichen unter http://localhost:9080/SecurityWeb/.
Troubleshooting und Security-Tipps
Version 1.0.0.1, Stand 15.12.2005
Historie:
1.0.0.0 (13.12.2005): Erstellt
1.0.0.1 (15.12.2005): Doku zu "redeployFileTransfer" erweitert: Rückgängigmachen und Screenshot für Ermitteln
von Cell, Node, Server. Ablaufdoku für Benutzervalidierung der UserRegistry.