Authentifizierung mit einem LDAP-Server: für Fortgeschrittene

Die Nutzer einer Application Express-Anwendung mit Hilfe eines LDAP-Servers zu authentifizieren, ist nicht besonders schwierig: Dazu gibt es ein vorgefertigtes Authentifizierungsschema; es müssen lediglich vier Angaben gemacht werden.

  • LDAP-Servername oder IP-Adresse
  • LDAP-Port
  • Den LDAP Distinguished Name String, also eine Maske für den LDAP-Anmeldenamen
  • Und optional: Die Username Edit Function, welche den vom Anwender angegebenen Nutzernamen u.U. umformatiert
Einrichtung des Authentifizierungsschemas "LDAP-Server"

Abbildung 1: Einrichtung des Authentifizierungsschemas "LDAP-Server"

Wird eine Anwendung mit einem solchen Authentifizierungsschema versehen, kann sich jeder im LDAP-Verzeichnis eingetragene Nutzer anmelden - und dies ist dann meist jeder im Unternehmen. In vielen Fällen reicht das jedoch nicht aus:

  1. Es ist denkbar, dass eine Anmeldung sowohl mit den Nutzerkonten im LDAP-Server als auch mit denen des Application Express-Workspace möglich sein soll.
  2. Im LDAP-Server sind meist für alle Beschäftigten eines Unternehmens Konten angelegt. Wenn nur bestimmte Nutzer Zugriff auf die Anwendung haben sollen, muss eine zusätzliche Prüfung erfolgen.
  3. Vielfach sind Nutzerinformationen auf mehrere LDAP-Server verteilt. Die Authentifizierung gegen einen LDAP-Server ist u.U. nicht ausreichend; eine zusätzliche zweite Authentifizierung gegen einen anderen LDAP-Server könnte erforderlich sein.

In diesen Fällen empfiehlt es sich, ein eigenes, benutzerdefiniertes Authentifizierungsschema zu erzeugen und darin alle nötigen Schritte auszuführen. Die Interaktion mit dem LDAP-Server erfolgt dabei mit dem PL/SQL-Paket DBMS_LDAP. In diesem Tipp wird das anhand eines Beispiels demonstiert: Die Authentifizierung soll mit Hilfe des LDAP-Servers erfolgen und zusätzlich sollen sich die im Application Express-Workspace hinterlegten Benutzer anmelden können. Allerdings sollen generell nur die Nutzer zugelassen werden, die in der Tabelle AUTORISIERTE_NUTZER stehen.

Wenn das Paket DBMS_LDAP in Ihrer Datenbank nicht vorhanden ist, muss es zunächst eingespielt werden. Dazu muss der DBA als SYS das Skript catldap.sql im Verzeichnis $ORACLE_HOME/rdbms/admin laufen lassen.

Erstellen Sie also zunächst im SQL Workshop die Tabelle und füllen Sie sie mit einigen Zeilen.

create table AUTORISIERTE_NUTZER(
  user_name       varchar2(200)
)
/

insert into AUTORISIERTE_NUTZER (user_name) values ('CARSTEN.CZARSKI')
/
insert into AUTORISIERTE_NUTZER (user_name) values ('ADMIN')
/

commit
/

Erstellen Sie anschließend die PL/SQL-Funktion USERNAME_PASSWORD_CHECK . Wichtig ist hierbei die Signatur der Funktion: Sie muss Nutzernamen und Passwort als VARCHAR2-Parameter entgegennehmen und das Ergebnis als BOOLEAN zurückliefern.

create or replace FUNCTION USERNAME_PASSWORD_CHECK (
  p_username in varchar2, 
  p_password in varchar2
) return boolean as
  v_login_result  boolean := false;
  v_ldap          raw(32);
  v_ldapres       binary_integer;
  v_un            varchar2(100);

  v_tableresult   number;
BEGIN
  --
  -- I. LDAP-Login 
  --
  begin
    -- LDAP-Handle initialisieren ...
    v_ldap := DBMS_LDAP.INIT(
      HOSTNAME => 'ldapserver.mydomain.com'
     ,PORTNUM  => 389
    );

    -- Hier wird der LDAP-"Distinguished Name" (DN) für das Login 
    -- zusammengesetzt; dies muss natürlich an die jeweilige Umgebung 
    -- angepasst werden.

    v_un := 'cn='||wwv_flow_custom_auth_std.ldap_dnprep(upper(p_username))||', dc=mydomain, dc=com';

    -- Der LDAP-Login-Versuch wird nur durchgeführt, wenn das
    -- Passwort NOT NULL ist - ansonsten nimmt der LDAP-Server
    -- an, dass ein "anonymous bind" vorliegt und wird jeden
    -- Versuch mit leerem Passwort "durchlassen"

    if p_password is not null then 

      -- Login-Versuch am LDAP-Server ...
       v_ldapres := DBMS_LDAP.SIMPLE_BIND_S(
        LD     => v_ldap,
        DN     => v_un,
        PASSWD => p_password
      );
  
      -- Bei Erfolg: wieder abmelden!
      v_ldapres := DBMS_LDAP.UNBIND_S(
        LD => v_ldap
      );
  
      -- Alles erfolgreich: Ergebnis auf "true" setzen
      v_login_result := true;
    else 
      v_login_result := false;
    end if;
  exception
    -- Bei Login-Misserfolg ... Ergebnis auf "false" setzen
    when others then
      v_login_result := false;
  end;


  --
  -- II. Login mit APEX-Nutzername 
  --
 
  -- Prüfung auf im APEX-Workspace eingetragenen Nutzer
  if not v_login_result then 
    v_login_result := APEX_UTIL.IS_LOGIN_PASSWORD_VALID(
      P_USERNAME => p_username,
      P_PASSWORD => p_password
    );
  end if;

  --
  -- III. Prüfung, ob Nutzer in der Tabelle AUTORISIERTE_NUTZER vorhanden ist
  --
  
  if v_login_result then
    begin
      select 1 into v_tableresult
      from AUTORISIERTE_NUTZER where user_name = p_username;
      v_login_result := true;
    exception
      when NO_DATA_FOUND then 
        v_login_result := false;
      when TOO_MANY_ROWS then 
        v_login_result := true;
    end;
  end if;

  return v_login_result;
END;
/

Wenn Sie den Code betrachten, erkennen Sie sehr gut die drei wesentlichen Abschnitte: Im ersten Abschnitt (I.) werden Nutzername und Passwort gegen den LDAP-Server geprüft. Dazu wird mit dem PL/SQL-Paket DBMS_LDAP ein Login (Bind) und unmittelbar danach ein Logout (Unbind) durchgeführt. Dieser Code läuft bei korrektem Benutzernamen und Passwort einwandfrei durch, bei falschen Angaben wird eine Exception ausgelöst. Ist der LDAP-Login nicht erfolgreich, wird in Abschnitt II mit der Funktion APEX_UTIL.IS_LOGIN_PASSWORD_VALID eine Prüfung anhand der eingetragenen Workspace-Nutzer vorgenommen. Wenn einer der beiden Abschnitte erfolgreich war, wird im letzten Abschnitt III geprüft, ob der Nutzer in der Tabelle AUTORISIERTE_NUTZER vorhanden ist. Das Ergebnis der Prüfung wird in der PL/SQL-Variablen v_login_result gespeichert: diese enthält am Ende - je nach Erfolg - den Wert true oder false.

Legen Sie nun ein neues Authentifizierungschema an. Navigieren Sie dazu zu den Gemeinsamen Komponenten, dort zu den Authentfizierungsschemas und klicken Sie dort auf Erstellen. Wählen Sie im folgenden Dialog Völlig neu aus (Abbildung 2).

Erstellen eines Authentifizierungsschemas "Völlig neu"

Abbildung 2: Erstellen eines Authentifizierungsschemas "Völlig neu"

Geben Sie Ihrem Authentifizierungsschema einen Namen und (optional) eine Beschreibung.

Namen und Beschreibung für das Authentifizierungsschema festlegen

Abbildung 3: Namen und Beschreibung für das Authentifizierungsschema festlegen

Übernehmen Sie nun bis zum Dialog Ungültiges Session-Ziel die Defaults. Dort wählen Sie die Seite 101 aus - die Application Express Integrierte Anmeldeseite ist nicht zu empfehlen (Abbildung 4).

Seite "101" als Login-Seite auswählen

Abbildung 4: Seite "101" als Login-Seite auswählen

Beim Prozeß vor der Authentifizierung klicken Sie wiederum einfach auf Weiter - die wichtigste Einstellung ist die dann folgende Authentifizerungsfunktion. Wählen Sie hier Meine benutzerdefinierte Funktion für die Authentifizierung verwenden aus und hinterlegen Sie im dann erscheinenden Textfeld "return USERNAME_PASSWORD_CHECK;"; das Schlüsselwort return ist hierbei sehr wichig (Abbildung 5).

Authentifizierungsfunktion hinterlegen

Abbildung 5: Authentifizierungsfunktion hinterlegen

Übernehmen Sie in den folgenden Dialogen wieder die Defaults, indem Sie stets auf Weiter klicken - im letzten Dialog Abmelde-URL tragen Sie folgende URL ein:

wwv_flow_custom_auth_std.logout?p_this_flow=&APP_ID.&p_next_flow_page_sess=&APP_ID.:1
Abmelde-URL hinterlegen

Abbildung 6: Abmelde-URL hinterlegen

Bestätigen Sie zum Schluß nochmals alle Angaben, in dem Sie in der Übersicht auf die Schaltfläche Schema erstellen klicken. Sie sehen daraufhin alle vorhandenen Schemas in einer Übersicht. Mit Klick auf Aktuelles Element ändern können Sie Ihrer Anwendung das neue Authentifizierungsschema zuweisen (Abbildungen 7 bis 9).

Erstelltes Authentifizierungsschema zuweisen

Abbildung 7: Authentifizierungsschema der Anwendung ändern

Authentifizierungsschema auswählen

Abbildung 8: Authentifizierungsschema auswählen

Änderung des Authentifizierungsschemas bestätigen

Abbildung 9: Änderung des Authentifizierungsschemas bestätigen

Nun können Sie das Authentifizierungsschema testen. Das gute daran ist, dass ein Nutzer, der zwar gültige Login-Daten eingibt, jedoch nicht in der Tabelle AUTORISIERTE_NUTZER enthalten ist, die gleiche Fehlermeldung erhält, wie jemand der falsche Login-Daten eingegeben hat, nämlich Invalid Login Credentials. Er erfährt also gar nichts über das Login-Schema der Applikation.

Tasks: Anwendungskomponenten exportieren unter "Gemeinsame Komponenten" Interessant wäre es nun, dieses Authentifizerungssschema auch anderen Application Express-Entwicklern zur Verfügung zu stellen - schließlich werden gerade solche Dinge wie ein LDAP-Login in den meisten Unternehmen zentral gesteuert. Für die PL/SQL-Funktion USERNAME_PASSWORD_CHECK ist das recht einfach - erstellen Sie einfach aus obigem Listing ein SQL-Skript; andere Entwickler spielen es dann via SQL Workshop ein. Allerdings möchten diese das Authentifizierungsschema nicht selbst Schritt für Schritt anlegen müssen; ein einfacher Import soll genügen. Daher empfiehlt es sich, das Authentifizierungsschema als einzelne Komponente zu exportieren. Navigieren Sie dazu wieder zu den Gemeinsamen Komponenten und klicken Sie rechts auf Anwendungskomponenten exportieren.

Im dann folgenden Dialog können Sie einzelne Anwendungskomponenten auswählen und so eine Exportdatei zusammenstellen. Wählen Sie Ihr eben erzeugtes Authentifizierungsschema aus und klicken Sie auf die Schaltfläche Zum Export hinzufügen. Nach gleicher Manier können Sie einzelne Seiten, Wertelisten, Templates und andere Dinge zu diesem Export hinzufügen - Sie können so "Standardkomponenten" für Ihr Unternehmen konfigurieren; jeder Entwickler kann diese Komponenten dann in seinen Workspace laden und für seine Anwendungen verwenden (Abbildung 10).

Komponenten für Export zusammenstellen

Abbildung 10: Komponenten für Export zusammenstellen

Klicken Sie, wenn Sie Ihre Komponenten zusammengestellt haben, auf Weiter und dann auf Komponentenexport (Abbildung 11)

Zusammengestellte Komponenten exportieren

Abbildung 11: Zusammengestellte Komponenten exportieren

Die SQL-Datei enthält die exportierten Komponenten - diese kann nun an andere Entwickler verteilt bzw. zum Download bereitgestellt werden.

Zurück zur Community-Seite