Wer denkt, Cocoon sei ein Club, ein Label oder ein Film, für den wird dieser Beitrag eine harte Nuss, es geht nämlich um Cocoon, das Web-Entwicklungs-Framework. Mit dem habe ich mich die letzten Tage und Wochen um die Ohren geschlagen und dabei Schritt für Schritt die Schwierigkeit erhöht. Problematisch erweist sich dabei, dass mit wachsender Schwierigkeit auch die Zahl der Webseiten sinkt, die einem weiterhelfen.
Level 1: May I introduce myself?
Um unsere Intranetabfrage vor unerlaubten Zugriffen zu schützen, sollte eine Authentifizierung integriert werden, die Abteilungen erlaubt, darauf zuzugreifen bzw. den Zugriff zu verhindern. Kein Problem – In der Dokumentation zum Cocoon gibt es eine Sektion, die Schritt für Schritt das Einrichten der Authenfizierung erläutert und wo man an welcher Stelle drehen muss, um ein bestimmtes Ergebnis zu erreichen.
Der Abruf einer Webseite beim Cocoon gliedert sich in drei Teile:
- Erzeugen der Daten (z.B. Datenbankabfrage)
- Transformation der Daten (optional)
- „Ausgabe“ der Daten
Diese Abfolge wird im Cocoon Pipeline genannt und bleibt für den Anwender völlig unsichtbar – er ruft nur eine Webseite auf, nach deren Namen die entsprechende Pipeline aufgerufen wird. Zur Authentifizierung wird um diese Abfolge ein Päckchen geschnürt, das den Zugriff schützt, der Handler. Der Authentifizierungshandler kennt zwei Pipelines: das Login und die Überprüfung der Nutzerdaten. Ist ein Nutzer eingeloggt, wird nur noch geprüft, ob der Nutzer eingeloggt ist und er auf die Daten zugreifen darf. Also integrierte ich anhand des Beispiels den Handler und ließ die Authentifikation gegen eine XML-Datei laufen. Wie gesagt, ganz einfach…
Level 2: Bürger, ihren Ausweis bitte!
Zur Überprüfung der Login-Daten sollte unser LDAP-Server dienen. Auch hier gab es erstmal kein Problem, im Cocoon ist ein LDAP-Transformator integriert, der mit XML beschriebene LDAP-Abfragen an den Server stellt und das Ergebnis wiederum als XML liefert. Nur beschränkt sich hier die Dokumentation des Cocoon einzig und allein darauf, wie das XML aufgebaut sein soll, was zur Abfrage dient. Also stöberte ich nach einigen Beispielen herum und gewann dabei mehrere Erkenntnisse…
- Die Daten der Authentifizierung werden in Form von XML gespeichert
- Diese Daten müssen einen bestimmten Aufbau haben, um akzeptiert zu werden
- Automatische Anmeldung geht nicht, denn auf die Umgebungsvariablen zurückzugreifen ist sinnlos. Was interessiert mich der Nutzername unter dem der Cocoon läuft? Ich will den Nutzernamen der Nutzers vor dem Browser!
Nach mehreren Anläufen und Versuchen unter Mithilfe unseres Admins hatte ich eine Abfrage fertig, die mir die entsprechenden Daten lieferte. Damit war das Problem erstmal gelöst. Ich konnte bestimmen, welche Abteilung sich anmelden darf und auf welche Seiten sie zugreifen darf. Aber damit hört es ja nicht auf…
Level 3: Im Zentrum der Maschinenwelt
Das Problem besteht ja nicht darin, nur eine Abteilung zuzulassen und die anderen auszusperren. Nein, unterschiedliche Abteilungen sollen auf verschiedene, ja sogar gleiche Seiten zugreifen können. Das Problem war: 1 Abteilung = 1 Authentifizierungshandler und 1 Webseite = 1 Authentifizierungshandler. Alles klar? Nö? Na dann… Ich kann den Zugriff auf eine Webseite nur mit einem Handler schützen. Dieser Handler überprüft die Nutzerdaten so, dass sie genau einem Kriterium entsprechen, in diesem Falle der Zugehörigkeit zur Abteilung. Also geht es nicht so einfach, zwei Handler auf eine geschützte Webseite zu bringen. Lösungsmöglichkeiten:
- Jeweils eine Pipeline pro Abteilung, aber mit unterschiedlichen Handlern (schlechte Idee, weil eine Unmenge an Code entsteht, der redundant ist)
- Für jede Mischungskombination von Abteilung einen neuen Authentifizierungshandler schreiben (ganz schlechte Idee, denn die Kombinationsmöglichkeiten wachsen mit n! [sprich: n Fakultät])
- Es gibt einen Handler, der nur prüft, ob die Abteilung auf die Intranetabfrage zugreifen darf. Mit den Nutzerdaten, die von der Authentifizierung als XML abgelegt sind, kann bestimmt werden, welchen Menüpunkt sie sehen dürfen und welchen nicht (Fantastische Lösung – das Menü baut sich dynamisch zusammen, je nach Login-Daten)
Die letzte Lösung klang nur zu schön. Seit Montag hab ich mich (neben anderen Sachen) damit herumgeärgert. Man suche im Netz: Eine Möglichkeit in einer eXtensible Server Page (XSP) das XML der Authentifizierung auszulesen (Die XSP gehört in der Pipeline in den Bereich der Datenerzeugung). Mit XSP kann man prima XML erzeugen und in der Transformation kann ich prima die Authentifizierungsdaten auslesen (Tja, leider zu spät), aber dazwischen – nichts! Bis heute Nachmittag… ich kämpfte mich schon durch die Javadoc’s des Cocoon, als ich plötzlich die Lösung fand. Zwar etwas unorthodox, aber es ging…
1
2
3
4
5
6
7
8
9 UserState ustate = ((UserState) <xsp:expr> <xsp-session:get-attribute name=<br />
"org.apache.cocoon.webapps.authentication.components.<br />
DefaultAuthenticationManager/UserStatus"/></xsp:expr>);
if (ustate.hasHandler())
{
UserHandler uhand = ustate.getHandler("handlername_as_defined_in_sitemap");
String username = uhand.getUserId();
...
}
Und wie drücke ich das am besten für Menschen verständlich aus? Man bekommt die Hauptspeise serviert und möchte aber schon wissen, was es als Nachspeise gibt. Die steht aber im Kühlschrank. Also guckt man, während die Hauptspeise serviert wird, durch die offene Küchentür und erkennt anhand der Sauerei in der Küche, was es als Nachtisch gibt. Deswegen müssen Programmierer immer so viel logisch denken – sonst gibt’s keinen Nachtisch 🙄 Au weia… ich muss gehen…