In diesem Beitrag beschreibe ich den Proof of Concept, den ich für einen unserer Kunden in den Niederlanden durchgeführt habe. Die Aufgabe bestand darin, Single Sign On mit der Weblogic Platform 10.2 Infrastruktur zu implementieren. Ich werde die verfügbaren Optionen für die Weitergabe von Sicherheitsinformationen erläutern und die Lösung beschreiben, die wir implementiert haben.
Unser Kunde richtet eine Plattform ein, um Dienste in einer SOA zu hosten. Die meisten dieser Dienste benötigen die Identität des Benutzers, um die Zugriffsrechte zu bestimmen. Die Idee ist, dass sich ein Benutzer bei einem Proxy-Server authentifiziert, um auf eine Seite im Weblogic Portal zuzugreifen. Die Portalseite verwendet in ALSB entwickelte Dienste, die wiederum an in WLI bereitgestellte Dienste delegieren. Ein Dienst in WLI kann andere Dienste in ALSB oder WLI aufrufen, um die Anfrage zu erfüllen und die Ergebnisse an den Benutzer zurückzugeben. Eine wichtige Anforderung war, dass eine Lösung so wenig invasiv wie möglich sein sollte. Das bedeutet, dass die Infrastruktur wann immer möglich dem Code vorgezogen wird. Ein wichtiger Aspekt der Infrastruktur ist, dass Portal, ALSB und WLI in getrennten Domänen laufen. Das bedeutet, dass Sicherheitsinformationen, insbesondere Sitzungsdaten, nicht ohne weiteres gemeinsam genutzt werden können.
Das folgende Sequenzdiagramm zeigt einen typischen Ablauf einer Anfrage durch die Infrastruktur.
Eine Benutzeranfrage trifft bei einem Proxy ein. Der Proxy überprüft die Anmeldeinformationen des Benutzers (Benutzername/Passwort, digitale Token, ...) in einer Novell eDirectory-Instanz und leitet die Anfrage an Portal weiter.
Die Zielplattform war Weblogic Platform 10.2 (einschließlich Portal 10.2, WLI 10.2 und Server 10.0) und ALSB 3.0. Die '2' in '10.2' scheint kein besonders wichtiges Detail zu sein, aber leider gibt es einen ziemlichen Unterschied zwischen den Standards, die von Plattform 10.2 und Plattform 10.3 unterstützt werden. Das Wichtigste ist, dass die erste Plattform SAML2.0 nicht unterstützt, die zweite dagegen schon.
Nachdem ich das Problem mit meinem Kunden besprochen hatte, kamen wir zu dem Schluss, dass SAML für uns die sauberste Implementierung wäre. SAML2.0 verwendet ein Sicherheits-Token, das zu einer Anfrage hinzugefügt werden kann. Dienste können die Authentizität des Tokens überprüfen und aus seinem Inhalt Zugriffsrechte ableiten. Leider würde die Verwendung von SAML2.0 Ergänzungen zum Server-Klassenpfad von Weblogic erfordern (d.h. dem Klassenpfad, der zum Starten der JVM verwendet wird, auf der Weblogic läuft). Eine der Ergänzungen wäre eine neue Implementierung der XML-Parsing-Bibliotheken. Dadurch würden wir die Oracle-Unterstützung verlieren, was nicht akzeptabel wäre. Die Migration auf die Weblogic Platform 10.3 würde eine Menge erneuter Tests von Anwendungen erfordern, so dass wir das für den Moment für zu viel Arbeit hielten.
Die zweitbeste Lösung, die uns einfiel, war SAML1.1, also versuchte ich, das in der oben skizzierten Architektur zu implementieren. Das Problem war nun, dass SAML1.1 anscheinend für die Verwendung durch Webbrowser gedacht ist: Sobald ein Benutzer bei SiteA authentifiziert ist und SiteB besucht, können SiteA und SiteB Sicherheits-Tokens über Browser-Redirects übertragen. Das Bild in sstc-saml-tech-overview-1.1-cd.pdf (siehe Seite 12) zeigt, was eigentlich passieren sollte. In meinem Fall gibt es eine Sitzung zwischen Browser und Portal, aber nicht zwischen Browser und ALSB oder Browser und WLI. Es findet keine Umleitung statt. Wir haben versucht, SAML1.1 in unserer Architektur zum Laufen zu bringen, mussten aber schließlich aufgeben.
Weiter zur nächsten Lösung: Übergabe von Benutzername und Passwort in WS-Security-Headern. Ich habe festgestellt, dass es eine Menge Verwirrung über WS-Security gibt. Zunächst war mir nicht klar, dass es sich lediglich um einen Transport für Sicherheitsinformationen handelt. Sie können WS-Security verwenden, um Sicherheitstoken in den Header eines Webdienstaufrufs einzufügen. Bei dem Token kann es sich um ein SAML2.0-Token oder um einen Benutzernamen und ein Passwort handeln.
In der Infrastruktur meines Kunden erfolgt der Zugriff auf das Portal über einen Proxy, der den Benutzer authentifiziert. Das bedeutet, dass Benutzername und Kennwort (oder jede andere Form von Sicherheits-Token) vom Proxy überprüft werden und dem Portal überhaupt nicht zur Verfügung stehen. Um eine Sitzung in dieser Architektur einzurichten, muss sich der Proxy beim Portal anmelden. In unserer Architektur war es am einfachsten, die Portalressourcen mit einer Basisauthentifizierung zu schützen.
Eine der Aufgaben der Proxy-Komponente ist die Zentralisierung der Zugriffsrechte: Ein Benutzer hat nur dann Zugriff, wenn ein gültiges Konto in einem Verzeichnis vorhanden ist, das vom Proxy überprüft wird. Die Anwendungen hinter dem Proxy verwalten die Rollenzugehörigkeit der Benutzer. Der Proxy hat für jede Anwendung ein eigenes Konto. So konnten wir eine Benutzername/Passwort-Kombination erstellen, die ausschließlich für Portal, ALSB und WLI verwendet wird. Das verwendete Passwort kann sich von dem Passwort unterscheiden, das der Benutzer kennt. Der Benutzer könnte sogar ein Client-Zertifikat oder ein von einem Token-Generator erzeugtes Einmal-Passwort haben. Diese 'externe Identität' wird vom Proxy in eine 'interne Identität' übersetzt.
In unserer Architektur baut der Proxy eine Sitzung mit Portal auf. Portal ruft dann Webservices auf und übergibt dabei Benutzername und Passwort in WS-Security-Headern. Dazu benötigt Portal den Benutzernamen und das Kennwort. Leider ist das Passwort für eine Anwendung, die in Portal eingesetzt wird, nicht verfügbar, der Benutzername hingegen schon (mit request.getUserPrincipal()). Wir haben dieses Problem gelöst, indem wir den Proxy veranlasst haben, Benutzername und Passwort als Header-Parameter zur Anfrage hinzuzufügen.
Portal erhält also eine Anfrage, sagen wir 'index.jsp', mit grundlegenden Authentifizierungsdaten und einem zusätzlichen Satz von Benutzernamen und Passwortdaten, die als Header-Parameter übergeben werden. Portal überprüft den Benutzernamen und das Kennwort mit dem Verzeichnis und startet eine Sitzung für den Benutzer. Die Daten für den Benutzernamen und das Kennwort werden aus der Anfrage abgerufen und in der serverseitigen Sitzung des Benutzers gespeichert:
[java]
String username = (String) request.getHeader('X-USERNAME');
String password = (String) request.getHeader('X-PASSWORD');
[/java]
(Übrigens gibt es für Firefox ein Plugin, mit dem Sie Header zu einer Anfrage hinzufügen können. Dies vereinfacht die Entwicklung, da ich nun testen kann, ohne den Proxy-Server installiert zu haben. Das Plugin heißt 'Modify Headers' und ist hier zu finden). Unter Verwendung des Benutzernamens und des Passworts konstruiert Portal einen Webservice-Aufruf. Der folgende Code fügt Benutzername und Kennwort zum WS-Security-Header hinzu
[java]
List credProvider = new ArrayList();
CredentialProvider cp = new ClientUNTCredentialProvider(username.getBytes(), password.getBytes());
credProviders.add(cp);
Stub stub = (Stub) port;
stub._setProperty(WSSecurityContext.CREDENTIAL_PROVIDER_LIST, credProviders);
[/java]
Der einfachste Weg, ALSB-Dienste zu konfigurieren, besteht darin, einen vorhandenen WLI-Dienst einzusetzen. Also habe ich den HelloWorld-Dienst, der mit Weblogic Platform installiert wurde, angepasst und ihn auf WLI bereitgestellt. Der WLI-Dienst verwendet die Webservice-Bibliothek von Weblogic, so dass die Sicherheit über Tags in der Java-Quelldatei hinzugefügt wird:
[java]
@Policies({
@Policy(uri='policy:Auth.xml', direction=Policy.Direction.inbound)
})
public class SecureHelloWorldImpl {
@WebMethod()
public String sayHello(String s) {
// Implementation goes here
}
}
[/java]
Der obige Code erzeugt einen Webdienst, der eine Zeichenkette akzeptiert und nur zugänglich ist, wenn der WS-Security-Header in der Anfrage eine Form der Authentifizierung enthält. Es ist einfach, den Dienst mit dem Client-Code zu testen, der in den Weblogic-Beispielen enthalten ist. Ich fand auch die Soap UI hilfreich, um eine Anfrage auf der Grundlage der WSDL für den Dienst zu erstellen.
In ALSB habe ich einen Geschäftsdienst unter Verwendung der WSDL erstellt, die vom Dienst in WLI erzeugt wurde. Zur Sicherheit verlassen sich unsere ALSB-Dienste auf die Dienste in WLI. Das bedeutet, dass Sie den ALSB-Dienst zwar aufrufen können, der Aufruf aber möglicherweise fehlschlägt, weil der Benutzer nicht über ausreichende Zugriffsrechte für den WLI-Dienst verfügt. Der Geschäftsdienst wird von einem ALSB-Proxy-Dienst aufgerufen, der das Routing für die Anfrage festlegt. Er kann die Anfrage auch ändern, daher habe ich die String-Ersetzungsfunktionen verwendet, um eine Kennzeichnung hinzuzufügen, mit der ich die Anfrage auf ihrem Weg durch die Infrastruktur verfolgen kann. Damit dies mit dem gesicherten WLI-Dienst funktioniert, müssen Sie dem ALSB-Projekt ein so genanntes Dienstkonto hinzufügen und es im Modus 'pass through' konfigurieren. Jetzt werden die Sicherheitsinformationen im WS-Security-Header an WLI weitergegeben. ALSB prüft die Sicherheit nicht selbst, aber in unserem Fall führt WLI alle erforderlichen Autorisierungen durch.
Die Grundlage für all dies ist das zentrale LDAP-Verzeichnis. Wir mussten jede Weblogic-Domäne so konfigurieren, dass sie die Zugriffsrechte in demselben Novell-Verzeichnis überprüft. Da Weblogic einen Authentifizierungsprovider für Novell anbietet, war dieser Teil einfach genug.
Zusammenfassend lässt sich sagen, dass eine Anfrage eines Benutzerbrowsers von einem Proxy-Server mit Benutzernamen und Passwortdaten angereichert wird. Der Proxy-Server delegiert an eine Portalanwendung, die durch eine einfache Authentifizierung geschützt ist. Die Portalseite erstellt eine Anfrage an WLI, die ALSB durchläuft. Das Weblogic Webservices-Framework verwendet die Sicherheitsinformationen im WS-Security-Header als Grundlage für seine Entscheidungen über die Zugriffsrechte.
Der Nettoeffekt ist, dass die Dienste in WLI mit der Identität des Endbenutzers aufgerufen werden können, ohne dass eine zusätzliche Sicherheitsprüfung im Geschäftscode erforderlich ist.
Eine Benutzeranfrage trifft bei einem Proxy ein. Der Proxy überprüft die Anmeldeinformationen des Benutzers (Benutzername/Passwort, digitale Token, ...) in einer Novell eDirectory-Instanz und leitet die Anfrage an Portal weiter.
Die Zielplattform war Weblogic Platform 10.2 (einschließlich Portal 10.2, WLI 10.2 und Server 10.0) und ALSB 3.0. Die '2' in '10.2' scheint kein besonders wichtiges Detail zu sein, aber leider gibt es einen ziemlichen Unterschied zwischen den Standards, die von Plattform 10.2 und Plattform 10.3 unterstützt werden. Das Wichtigste ist, dass die erste Plattform SAML2.0 nicht unterstützt, die zweite dagegen schon.
Nachdem ich das Problem mit meinem Kunden besprochen hatte, kamen wir zu dem Schluss, dass SAML für uns die sauberste Implementierung wäre. SAML2.0 verwendet ein Sicherheits-Token, das zu einer Anfrage hinzugefügt werden kann. Dienste können die Authentizität des Tokens überprüfen und aus seinem Inhalt Zugriffsrechte ableiten. Leider würde die Verwendung von SAML2.0 Ergänzungen zum Server-Klassenpfad von Weblogic erfordern (d.h. dem Klassenpfad, der zum Starten der JVM verwendet wird, auf der Weblogic läuft). Eine der Ergänzungen wäre eine neue Implementierung der XML-Parsing-Bibliotheken. Dadurch würden wir die Oracle-Unterstützung verlieren, was nicht akzeptabel wäre. Die Migration auf die Weblogic Platform 10.3 würde eine Menge erneuter Tests von Anwendungen erfordern, so dass wir das für den Moment für zu viel Arbeit hielten.
Die zweitbeste Lösung, die uns einfiel, war SAML1.1, also versuchte ich, das in der oben skizzierten Architektur zu implementieren. Das Problem war nun, dass SAML1.1 anscheinend für die Verwendung durch Webbrowser gedacht ist: Sobald ein Benutzer bei SiteA authentifiziert ist und SiteB besucht, können SiteA und SiteB Sicherheits-Tokens über Browser-Redirects übertragen. Das Bild in sstc-saml-tech-overview-1.1-cd.pdf (siehe Seite 12) zeigt, was eigentlich passieren sollte. In meinem Fall gibt es eine Sitzung zwischen Browser und Portal, aber nicht zwischen Browser und ALSB oder Browser und WLI. Es findet keine Umleitung statt. Wir haben versucht, SAML1.1 in unserer Architektur zum Laufen zu bringen, mussten aber schließlich aufgeben.
Weiter zur nächsten Lösung: Übergabe von Benutzername und Passwort in WS-Security-Headern. Ich habe festgestellt, dass es eine Menge Verwirrung über WS-Security gibt. Zunächst war mir nicht klar, dass es sich lediglich um einen Transport für Sicherheitsinformationen handelt. Sie können WS-Security verwenden, um Sicherheitstoken in den Header eines Webdienstaufrufs einzufügen. Bei dem Token kann es sich um ein SAML2.0-Token oder um einen Benutzernamen und ein Passwort handeln.
In der Infrastruktur meines Kunden erfolgt der Zugriff auf das Portal über einen Proxy, der den Benutzer authentifiziert. Das bedeutet, dass Benutzername und Kennwort (oder jede andere Form von Sicherheits-Token) vom Proxy überprüft werden und dem Portal überhaupt nicht zur Verfügung stehen. Um eine Sitzung in dieser Architektur einzurichten, muss sich der Proxy beim Portal anmelden. In unserer Architektur war es am einfachsten, die Portalressourcen mit einer Basisauthentifizierung zu schützen.
Eine der Aufgaben der Proxy-Komponente ist die Zentralisierung der Zugriffsrechte: Ein Benutzer hat nur dann Zugriff, wenn ein gültiges Konto in einem Verzeichnis vorhanden ist, das vom Proxy überprüft wird. Die Anwendungen hinter dem Proxy verwalten die Rollenzugehörigkeit der Benutzer. Der Proxy hat für jede Anwendung ein eigenes Konto. So konnten wir eine Benutzername/Passwort-Kombination erstellen, die ausschließlich für Portal, ALSB und WLI verwendet wird. Das verwendete Passwort kann sich von dem Passwort unterscheiden, das der Benutzer kennt. Der Benutzer könnte sogar ein Client-Zertifikat oder ein von einem Token-Generator erzeugtes Einmal-Passwort haben. Diese 'externe Identität' wird vom Proxy in eine 'interne Identität' übersetzt.
In unserer Architektur baut der Proxy eine Sitzung mit Portal auf. Portal ruft dann Webservices auf und übergibt dabei Benutzername und Passwort in WS-Security-Headern. Dazu benötigt Portal den Benutzernamen und das Kennwort. Leider ist das Passwort für eine Anwendung, die in Portal eingesetzt wird, nicht verfügbar, der Benutzername hingegen schon (mit request.getUserPrincipal()). Wir haben dieses Problem gelöst, indem wir den Proxy veranlasst haben, Benutzername und Passwort als Header-Parameter zur Anfrage hinzuzufügen.
Portal erhält also eine Anfrage, sagen wir 'index.jsp', mit grundlegenden Authentifizierungsdaten und einem zusätzlichen Satz von Benutzernamen und Passwortdaten, die als Header-Parameter übergeben werden. Portal überprüft den Benutzernamen und das Kennwort mit dem Verzeichnis und startet eine Sitzung für den Benutzer. Die Daten für den Benutzernamen und das Kennwort werden aus der Anfrage abgerufen und in der serverseitigen Sitzung des Benutzers gespeichert:
[java]
String username = (String) request.getHeader('X-USERNAME');
String password = (String) request.getHeader('X-PASSWORD');
[/java]
(Übrigens gibt es für Firefox ein Plugin, mit dem Sie Header zu einer Anfrage hinzufügen können. Dies vereinfacht die Entwicklung, da ich nun testen kann, ohne den Proxy-Server installiert zu haben. Das Plugin heißt 'Modify Headers' und ist Verfasst von

Jan Vermeir
Developing software and infrastructure in teams, doing whatever it takes to get stable, safe and efficient systems in production.
Unsere Ideen
Weitere Blogs
Contact
Let’s discuss how we can support your journey.



