Eine App zur Verwaltung von Benutzern in einer Datenbank.

1. Übersicht

Die Java-Plattform spezifiziert die sogenannte Container Managed Security nach der ein Server sicherstellt, dass nur Benutzer im Besitz der passenden Rolle die Ressourcen einer App nutzen können. Apps deklarieren hierfür die Rollen, die ein Benutzer für die Nutzung bestimmter Ressourcen besitzen muss.

Server wie beispielsweise Tomcat implementieren die Container Managed Security vollumfänglich, überlassen die Implementierung der Berechtigungsverwaltung aber dem Betreiber der jeweiligen Server-Instanz. Bereits bestehende zentrale Systeme, zum Beispiel LDAP- oder Active-Directory-Server zur Benutzerverwaltung lassen sich so auch für Tomcat einsetzen.

Für viele Verwendungen von Tomcat, bei denen sich der Betrieb eines LDAP- oder Active-Directory-Servers nicht lohnt, ist allerdings der standardmäßig eingerichtete Mechanismus für eine rudimentäre Benutzerdatenbank nicht ausreichend. Beispielsweise muss der Server für jede Änderung an Benutzern oder Rollen neu gestartet werden.

Die Nutzerverwaltung liefert eine Alternative zur Verwaltung von Benutzern und Rollen, bei der jede Änderung im laufenden Betrieb ohne Neustart des Servers stattfinden kann. Die Bedienung ist zudem universell im Browser möglich und kann von vielen unterschiedlichen Geräten aus erfolgen.

2. Installation

Die Installation der Nutzerverwaltung erfordert u.a. eine Umstellung des Realm von Tomcat (vgl. Realm: Database of users, passwords, and their associated roles for use in web applications that utilize Container Managed Security). Aus diesem Grund ist die Installation der Nutzerverwaltung umfangreicher als der bei Java-Webanwendungen sonst übliche einfache 'Deploy' einer .war-Datei. Die folgenden Schritte sind zusätzlich erforderlich und müssen in der angegebenen Reihenfolge ausgeführt werden.

2.1. Bestandteile beschaffen

Die Nutzerverwaltung erfordert eine Ablaufumgebung bestehend aus Server und Datenbank. Für dieses Dokument wird davon ausgegangen, dass Java, Tomcat und Derby bereits eingerichtet wurden.

Die folgenden Elemente müssen darüber hinaus lokal bereit stehen und im ersten Schritt beschafft werden. Sie sind an den unten angegebenen Orten frei erhältlich.

  1. Serialisierung und Deserialisierung für Java-Objekte: XStream herunterladen

  2. Transformation von und nach JSON: Jettison herunterladen

  3. Templates für Javascript: Mustache herunterladen

  4. Datenbank-Zugriffsschicht: BaseLink herunterladen

  5. Paket der Nutzerverwaltung herunterladen

  6. Pakete entpacken

Damit ist alles bereit zur Installation.

2.2. Bibliotheken installieren

Aus den im vorigen Schritt geladenen und entpackten Paketen müssen die folgenden Dateien lokalisiert und kopiert werden. $CATALINA_BASE meint hierbei das in der Datei RUNNING.txt der Tomcat-Dokumentation so bezeichnete Verzeichnis, auf Linux kann dies beispielsweise /usr/local/tomcat sein.

  • xstream-1.4.7.jar, jettison-1.3.3.jar, BaseLink.jar und derbyclient.jar im Verzeichnis $CATALINA_BASE/lib ablegen

  • mustache.min.js im Verzeichnis $CATALINA_BASE/webapps/jslib/mustache ablegen

Anschließend muss Tomcat neu gestartet werden, damit die Bibliotheken für die Installation und den Start der Nutzerverwaltung laut den folgenden Schritten einbezogen werden können.

2.3. Datenbankserver starten

Sofern noch kein Derby-Datenbankserver läuft muss dieser nun gestartet werden. Die Nutzerverwaltung ist mit einer DataSource konfiguriert, die auf jdbc:derby://localhost:1527 verweist. Wenn der Datenbankserver über einen anderen URL eingebunden werden soll, muss dies in der Datei META-INF/context.xml des Archivs um.war vor der Installation des Archivs umgestellt werden.

Wie beispielsweise im Tipp: Derby Network Server beschrieben wird üblicherweise beim Start des Datenbankservers der Ablageort von Datenbanken mit dem Parameter -Dderby.system.home=/pfad/zu/datenbanken angegeben. An dieser Stelle wird dann auch die Datenbank der Nutzerverwaltung angelegt.

2.4. Nutzerverwaltung installieren

Zur Installation der Nutzerverwaltung wird die Datei um.war aus dem heruntergeladenen Paket im Verzeichnis $CATALINA_BASE/webapps von Tomcat abgelegt ('deploy'). Es kann auch der Tomcat-Manager verwendet werden. Mit dem Deploy der Nutzerverwaltung wird die App gestartet. Beim ersten Start wird automatisch die Benutzerdatenbank udb angelegt. Die Nutzerverwaltung kann nun mit dem URL http://localhost:8080/um/ui im Browser aufgerufen werden.

Wichtig: Mit diesem Schritt ist die Nutzerverwaltung als App verwendbar. Die in der Nutzerverwaltung vorgenommenen Einträge zu Benutzern und Rollen sind aber noch nicht für den Server wirksam, auf dem die App läuft. Diese Konfiguration erfolgt erst im nächsten Schritt Konfiguration anpassen.

Beim ersten Start der Nutzerverwaltung wird automatisch der Benutzer admin mit Kennwort admin erstellt. Dieser Nutzer sollte gleich als Erstes verwendet werden, um einen anderen Benutzer mit Administrationsrechten anzulegen. Der Nutzer muss mindestens die Rollen manager-script, nutzerAdmin und nutzerProfil erhalten.

Sobald nach der Konfiguration im folgenden Schritt die Anmeldung mit dem neu angelegten Nutzer gelingt, kann später der Benutzer admin gelöscht werden.

2.5. Konfiguration anpassen

Damit der Server die Datenbank der Nutzerverwaltung für die Container Managed Security verwendet müssen in der Datei $CATALINA_BASE/conf/server.xml nach der Installation der Nutzerverwaltung die DataSource der Nutzerverwaltung hinzugefügt und der Realm von Tomcat auf die Nutzerdatenbank umgestellt werden wie nachfolgend beschrieben.

2.5.1. DataSource hinzufügen

Zu Beginn der Datei $CATALINA_BASE/conf/server.xml wird die DataSource angegeben, die den Ablageort der Benutzerdatenbank angibt:

Eintrag der DataSource für die Benutzerdatebank in der Datei server.xml
  <!-- Global JNDI resources
       Documentation at /docs/jndi-resources-howto.html
  -->
  <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->
    <Resource name="UserDatabase" auth="Container"
              type="org.apache.catalina.UserDatabase"
              description="User database that can be updated and saved"
              factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
              pathname="conf/tomcat-users.xml" />

    <Resource name="jdbc/NewUserDB"
		  auth="Container"
		  type="javax.sql.DataSource"
		  driverClassName="org.apache.derby.jdbc.ClientDriver"
		  url="jdbc:derby://localhost:1527/udb;create=true"
		  maxActive="60"
		  maxIdle="30"
		  maxWait="5000"
	  />
  </GlobalNamingResources>

Wenn der Datenbankserver nicht wie oben angegeben unter dem URL jdbc:derby://localhost:1527 erreichbar ist, muss stattdessen der entsprechend passende URL eingetragen werden.

2.5.2. Realm umstellen

Weiter unten in der Datei $CATALINA_BASE/conf/server.xml ist der Realm angegeben, der die Benutzerdaten für Authentifizierung und Autorisierung an Tomcat übergibt. Er lautet standardmäßig wie folgt:

Die Datei server.xml vor der Umstellung des Realm
<Engine name="Catalina" defaultHost="localhost">

  <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase"/>
  </Realm>

  <!-- weitere Einträge ... -->

Nach der Umstellung des Realm auf die Datenbank der Nutzerverwaltung lautet der Eintrag:

Die Datei server.xml nach der Umstellung des Realm
<Engine name="Catalina" defaultHost="localhost">

  <Realm className="org.apache.catalina.realm.LockOutRealm">
    <Realm className="org.apache.catalina.realm.DataSourceRealm"
        dataSourceName="jdbc/NewUserDB"
        userTable="users" userNameCol="user_name" userCredCol="user_pass"
        userRoleTable="user_roles" roleNameCol="role_name">
        <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="sha-256" />
	</Realm>
  </Realm>

  <!-- weitere Einträge ... -->

Nach einem Neustart von Tomcat werden die Änderungen wirksam und die Nutzerverwaltung ist für den Server fertig eingerichtet.

3. Nutzerverwaltung

Zur Verwendung der Nutzerverwaltung müssen Benutzer die Rolle nutzerAdmin besitzen. Nach erfolgreicher Installation kann die Nutzerverwaltung mit folgendem URL aufgerufen werden:

http://localhost:8080/um/ui

Beim Aufruf des obigen URL erscheint nach erfolgreicher Anmeldung die Liste der Benutzer. Dort lassen sich die folgenden Funktionen durchführen:

  • Neuen Benutzer anlegen

  • Benutzer löschen

  • Rolle erteilen

  • Rolle entziehen

Diese Funktionen sind nachfolgend genauer beschrieben.

3.1. Benutzer anlegen

In der Ansicht mit der Liste der Benutzer wird mit Betätigen der Schaltfläche mit dem Benutzer-Piktogramm oben rechts ein Formular zum Anlegen eines neuen Benutzers angezeigt. Hier muss eine eindeutige Kennung vergeben werden, die dem neuen Nutzer zur Anmeldung dient.

Die übrigen Angaben Name, Vorname und E-Mail-Adresse sind zusätzliche Informationen, die im Kontext der Nutzerverwaltung nicht verwendet werden. Sie dienen nur der besseren Erkennung, um welche Person es sich beim betreffenden Benutzer handelt.

Die zusätzlichen Angaben können von anderen Anwendungen genutzt werden, um beispielsweise den Namen des angemeldeten Nutzers anzuzeigen oder dem Benutzer per E-Mail eine Nachricht beispielsweise eine Benachrichtigung zum Ändern des Kennwortes zu senden.

3.1.1. Kennwort

Zur neuen Benutzerkennung muss ein Kennwort angegeben werden, das zur Vermeidung von Tippfehlern ein zweites Mal abgefragt wird. Das auf diese Weise neuen Benutzern initial vergebene Kennwort kann nur vom betreffenden Benutzer selbst geändert werden. Die Änderung erfolgt mit Hilfe des Nutzerprofils.

3.2. Rolle erteilen oder entziehen

Nach der erfolgreichen Anmeldung an der Nutzerverwaltung erscheint die Liste der Benutzer. Anklicken bzw. Antippen eines Benutzers in der Liste zeigt die Rollen dieses Benutzers. Anklicken einer Rolle erteilt oder entzieht die Rolle abhängig davon, ob sie im Bereich der erteilten Rollen oder im Bereich der verfügbaren Rollen angeklickt wurde.

3.2.1. Neue Rolle erteilen

Ist die gewünschte Rolle nicht unter den verfügbaren Rollen aufgelistet kann mit Betätigen der Schaltfläche mit dem Benutzer-Piktogramm oben rechts der Name einer neuen Rolle angegeben werden, die dann dem Benutzer erteilt wird.

3.3. Benutzer löschen

Zum Löschen eines Benutzers wird der Benutzer zunächst aus der Liste der Benutzer ausgewählt. In der daraufhin erscheinenden Ansicht der Rollen des Benutzers kann zum Löschen des Benutzers die rötliche Schaltfläche oben rechts betätigt werden.

4. Nutzerprofil

Mit dem Nutzerprofil kann der angemeldete Benutzer sein eigenes Kennwort ändern. Nutzer müssen dafür die Rolle nutzerProfil besitzen. Das Nutzerprofil kann mit dem folgenden URL aufgerufen werden

http://localhost:8080/um/profil

Ein Aufruf gelingt nur, wenn der Benutzer angemeldet ist, andernfalls erscheint zunächst die Anmeldeaufforderung. Nach erfolgreicher Anmeldung erscheint die Ansicht zum Ändern des eigenen Kennwortes. Diese Funktion lässt sich nur für die Daten des angemeldeten Nutzers ausführen, ein angemeldeter Benutzer kann den Funktionsaufruf zum Ändern des Kennwortes nicht für einen anderen Benutzer verwenden.

Eine Änderung der Nutzerdaten (Name, Vorname, E-Mail-Adresse) kann nicht direkt vorgenommen werden. Ein Benutzer mit der Rolle nutzerAdmin muss hierzu den Nutzer löschen, neu anlegen, dabei die neuen Benutzerdaten angeben sowie die Rollen wieder herstellen.

5. Programmschnittstelle

(Dieser Teil ist noch in Arbeit)

Die Nutzerverwaltung stellt drei Bereiche bereit

Table 1. Die Service-Endpunkte der Nutzerverwaltung
Bereich Pfad Rolle

Nutzer und Rollen

/um/api

nutzerAdmin

Nutzerprofil

/um/prf

nutzerProfil

Session-Info

/um/pub

keine

Alle obigen Bereiche sind über das TransitServlet zugänglich. Der Enpunkt api wird zudem umgesetzt auf den Endpunkt svc:

http://example.com/um/svc/testmethode
  wird umgesetzt auf
http://example.com/um/api?c=de.uhilger.um.api.UserMgr&m=testmethode

Dabei bleibt der Query-Teil erhalten wie in

http://example.com/um/svc/testmethode?p=param1&p=param2

Und es kann ebenso mit PUT oder POST gearbeitet werden, beispielsweise mit HTTP POST an

http://example.com/um/svc/testmethode`
  mit
var data = 'p=param1&p=param2'

5.1. getSessionUser

Die Methode getSessionUser liefert Kennung, Name und E-Mail-Adresse des in der aktuell laufenden Sitzung gerade angemeldeten Benutzers. Andere Apps können diese Methode nutzen um anzuzeigen, wer gerade angemeldet ist.

Aufruf: http://example.com/um/pub?c=de.uhilger.um.pub.SessionManager&m=getSessionUser

Die Antwort auf eine Anfrage an getSessionUser
{
  "UserData":{
     "id":"ulrich",
     "firstName":"Ulrich",
     "lastName":"Hilger",
     "email":"ulrich@example.com"
  }
}

5.2. expireSession

Die Methode expireSession bewirkt, dass die aktuelle Sitzung auf dem Server als abgelaufen markiert wird. Andere Apps können diese Methode benutzen, um den aktuell angemeldeten Benutzer abzumelden.

Aufruf: http://example.com/um/pub?c=de.uhilger.um.pub.SessionManager&m=expireSession

Antwort: "Die aktuelle Sitzung ist nicht mehr gueltig."