JAAS steht für Java Authentication and Authorization Service und bietet uns im Java EE Umfeld unter anderem die Möglichkeit einen standardisierten Mechanismus zu verwenden um einen Benutzer zu autorisieren. Der Wildfly 10 bringt eine ganze Reihe solcher Login Module mit, bietet uns aber auch die Möglichkeit ein solches Modul selber zu schreiben.
Die Liste der zur Verfügung stehenden Möglichkeiten einen Benutzer zu autorisieren ist im Wildfly 10 schon recht umfangreich. Angefangen von einfachen .properties-Dateien, über relationale Datenbanken und Zertifikate bis hin zu LDAP-Abfragen ist alles möglich. Sollten wir jedoch in einem konkreten Fall mit diesen Mitteln nicht auskommen, z.B. weil die Login Informationen in einem bestehenden System über eine Schnittstelle zur Verfügung gestellt werden, lässt der Standard uns auch ein eigenes solches Modul implementieren.
Implementierung
Beginnen wir bei der Implementierung eines solches Moduls. Diese Klasse muss das Interface javax.security.auth.spi.LoginModul implementieren und somit folgende Methoden zur Verfügung stellen:
- initialize(…) – Initialisierung des Modules
- login() – Login Prüfung
- logout() – führt einen Logout durch
- commit() – Methode wird nach erfolgreichem Login aufgerufen
- abort() – Methode wird bei nicht erfolgreichem Login aufgerufen
Auffällig ist das die „login“ Methode keinerlei Parameter annimmt, wie es vielleicht zu erwarten wäre. Der Zugriff auf diese, vom Benutzer je nach Auth-Method unterschiedlich zur Verfügung gestellte, Eingabe erhält man über die Verwendung so genannter Callback-Methoden. Die Prüfung auf einen gültigen Login erfolgt dann ganz nach eigenen Wünschen und führt im Erfolgsfall dazu, dass ein Principal dem aktuellen Subject (Aufrufer) hinzugefügt wird
public boolean login() throws LoginException { NameCallback nameCallback = new NameCallback("Benutzer"); PasswordCallback passwordCallback = new PasswordCallback("Password", false); try { callbackHandler.handle(new Callback[]{nameCallback, passwordCallback}); String username = nameCallback.getName(); String password = new String(passwordCallback.getPassword()); if (logInWS(username, password)) { loggedIn = true; identity = new UserPrincipal(username); subject.getPrincipals().add(identity); subject.getPublicCredentials().add(identity); return true; } } catch (IOException e) { e.printStackTrace(); } catch (UnsupportedCallbackException e) { e.printStackTrace(); } return false; }
Nachdem die Login Methode erfolgreich durchlaufen wurde, folgt der Aufruf der Methode „commit“ in der in aller Regel die für den Principal gültigen Rollen aufgebaut werden. Hierfür werden entsprechende Implementierungen von java.security.acl.Group und java.security.Principal benötigt. Diese sind sehr leicht selber zu schreiben (s. Github) oder wir bedienen im Fall von JBoss bei „Picketbox“ (Security Implementierung des Wildfly, Maven:org.picketbox/jbosssx-bare ).
public boolean commit() throws LoginException { if (loggedIn) { Group group = new SimpleGroup("Roles"); SimplePrincipal role = new SimplePrincipal("super-user"); group.addMember(role); subject.getPrincipals().add(group); return true; } return false; }
Konfiguration
Damit das Ganze vom Wildfly und unserer Anwendung auch erkannt und verwendet wird, sind noch einige Konfigurationen notwendig. So muss eine entsprechende Security Domain im Wildfly konfiguriert werden. Hier wird neben der Implementierungs-Klasse auch ein entsprechender Namen vergeben. Die Implementierung muss in diesem Fall innerhalb der Anwendung zur Verfügung stehen. Alternativ dazu kann das Login Modul auch als WildflyModul bereitgestellt werden, dann muss lediglich das Attribut „module“ beim „login-module“ mit entsprechendem Namen des Moduls ergänzt werden.
standalone.xml
... <security-domain name="MySecurityDomain" cache-type="default"> <authentication> <login-module code="de.gedoplan.custom.jaas.CustomJAASLoginModule" flag="required"/> </authentication> </security-domain> ...
Schlussendlich muss die im Beispiel verwendete Webanwendung mit EJB-Komponenten mit entsprechenden Jboss-Konfigurationen versehen werden, sodass unser angelegte Security Domain auch Verwendung findet
jboss-web.xml
<jboss-web> <security-domain>java:/jaas/MySecurityDomain</security-domain> <default-encoding>UTF-8</default-encoding> </jboss-web>
jboss-ejb3.xml
<jboss:jboss xmlns="http://java.sun.com/xml/ns/javaee" xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:s="urn:security:1.1" version="3.1" impl-version="2.0"> <assembly-descriptor> <s:security> <ejb-name>*</ejb-name> <s:security-domain>MySecurityDomain</s:security-domain> </s:security> </assembly-descriptor> </jboss:jboss>