Beispiel: JBoss-spezifische Security


Inhalt:

Anlegen der Application
Anlegen des Projekts für das Login-Modul
Export und Import des Login-Modul-Projekts
Datenbank vorbereiten
Code und Config des Login-Moduls
EJB-Projekt
Web-Projekt
Application Client-Projekt

Dieses Beispiel entspricht dem WebSphere-UserRegistry-Beispiel, ist aber auf den JBoss angepaßt. Es zeigt wie das Validieren eines Logins über ein eigenes Login-Modul funktioniert, außerdem wird die J2EE-Security gezeigt.
Aufbau des Beispiels: Hier gibt es die Enterprise Application zum Download: Security.ear. Die Importanleitung findet man im Stateless-Beispiel.
Das Login-Modul-Projekt muss separat heruntergeladen werden: SecurityLoginModule.zip Die Import-Anleitung steht hier. Wichtig: beim erstmaligen Import müssen zwei Classpath Variables angelegt werden, siehe Anleitung für das Erzeugen des Projekts "SecurityLoginModule".


Anlegen der Application

Ein "EAR Application Project" mit dem Namen "Security" wird erstellt. Im zweiten Schritt müssen wir an den Facets nichts ändern.
In Schritt 3 erstellen wir ein Web Module, Application Client Module und ein EJB Module.
New application


Anlegen des Projekts für das Login-Modul

JBoss bietet ein integriertes Login-Modul org.jboss.security.auth.spi.DatabaseServerLoginModule, das es erlaubt User direkt gegen zwei Datenbanktabellen zu authentifizieren: eine Tabelle liefert User und Passwort, eine zweite Tabelle die Rollen der User. Ein Beispiel für die Verwendung dieses Login-Moduls findet sich in der Datei "%JBOSS_HOME%\server\default\conf\login-config.xml". Es ist leider für unser Beispiel nicht ausreichend da wir zwei Tabellen für die User benötigen und die Rollen sich direkt aus der Tabelle ergeben in der der User gefunden wird.
Um den Login gegen unsere Datenbanktabellen zu realisieren benötigen wir also ein eigenes Login-Modul. Dieses könnten wir in oben erwähnter Config-Datei "login-config.xml" eintragen, sauberer ist es jedoch es sauber in eine Zip-Datei zu verpacken die mit unserer Anwendung zusammen ausgeliefert wird.
Dies geschieht beim JBoss über "Service archives", kurz SAR (ganz normale Zip-Archive), die Konfigurationen und Erweiterungen für den MBean-Mechanismus enthalten.
Das folgende Beispiel habe ich in Teilen aus dem JBoss-Guide (
http://docs.jboss.org/jbossas/jboss4guide/), Kapitel "8.4.7.2. A Custom LoginModule Example", gezogen.

Wir legen uns also ein neues Java-Projekt "SecurityLoginModule" an. Einzige Besonderheit: wir wünschen uns unterschiedliche Ordner für Quellcode und class-Dateien.
Projekt "SecurityLoginModule"
Es taucht unter "Other Projects" auf.

Zuallererst müssen wir zwei JAR-Dateien des JBoss-Servers im Projekt referenzieren: "%JBOSS_HOME%\server\default\lib\jbosssx.jar" und "%JBOSS_HOME%\client\jbossall-client.jar". Wir gehen in "Window" -> "Preferences" in den Zweig "Java" -> "Build Path" -> "Classpath Variables". Hier fügen wir eine neue hinzu. Sie bekommt den Namen "JBOSSSX", der Pfad zeigt auf "%JBOSS_HOME%\server\default\lib\jbosssx.jar".
Variable JBOSSSX
Dito für eine zweite Variable "JBOSSALLCLIENT", die auf "%JBOSS_HOME%\client\jbossall-client.jar" verweist. Dieser Verweis ist bei den J2EE-Projekten bereits über die JBoss-Serverdefinition enthalten, hier muss sie leider manuell zugefügt werden.
Variable JBOSSALLCLIENT
Das Ergebnis sieht so aus:
Classpath Variables

Jetzt geht es in die Properties des Projekts. Unter "Java Build Path" -> "Libraries" klicken wir auf "Add Variable..". Im erscheinenden Dialog "New Variable Classpath Entry" wählen wir die eben angelegten Variablen aus.
Add Variable (1)
Das Ergebnis sieht so aus:
Add Variable (2)


Export und Import des Login-Modul-Projekts

Export:
Das Login-Modul-Projekt kann nicht zusammen mit der EAR-Datei exportiert werden. Deshalb müssen wir es als "Archive file" exportieren. Bei den zu exportierenden Elementen wählen wir das gesamte Projekt, ausgenommen bleibt nur das bin-Verzeichnis (da stecken nur die class-Dateien drin). Wichtig ist dass die Option "Create only selected directories" gesetzt wird und dass die Checkbox vor "SecurityLoginModule" nicht gesetzt ist!
Export SecurityLoginModule

Re-Import
Vor dem Re-Import müssen wir zuerst ein Java-Projekt "SecurityLoginModule" anlegen, idealerweise mit den gleichen Optionen wie oben beschrieben.
Anschließend importieren wir ein "Archive file". Im Feld "Into Folder" geben wir den Namen des eben angelegten Projekts an.
Import SecurityLoginModule


Datenbank vorbereiten

In der Datenbank werden die benötigten Tabellen erzeugt und jeweils ein Testdatensatz angelegt:
CREATE TABLE KUNDE 
(ID int not null, 
NAME varchar(100), 
LOGIN varchar(100), 
PASSWORT varchar(100) );

CREATE TABLE ADMINISTRATOR 
(ID int not null, 
NAME varchar(100), 
LOGIN varchar(100), 
PASSWORT varchar(100) );

insert into ADMINISTRATOR (ID, LOGIN, NAME, PASSWORT) values  (1, 'ADMIN', 'Admin', 'ADMIN');
insert into KUNDE (ID, LOGIN, NAME, PASSWORT) values  (1, 'DOOFI', 'DOOFI', 'DOOFI'); 


Code und Config des Login-Moduls

Im Package de.fhw.swtvertiefung.knauf.security.loginmodule werden drei Dateien zugefügt: Jetzt legen wir ein Verzeichnis "meta-inf" im Projekt an und fügen dort zwei Dateien zu:
jboss-service.xml ist die Kerndatei des Service Archives. Über sie initialisiert der Server das Modul. Wir deklarieren hier wie unsere Config in den Server gelangen soll:
<?xml version="1.0" encoding="UTF-8"?>
<server>   
   <mbean code="org.jboss.security.auth.login.DynamicLoginConfig"
     name="jboss:service=DynamicLoginConfig">
     <attribute name="AuthConfig">META-INF/login-config.xml</attribute>
     <depends optional-attribute-name="LoginConfigService">
       jboss.security:service=XMLLoginConfig
     </depends>
     <depends optional-attribute-name="SecurityManagerService">
       jboss.security:service=JaasSecurityManager
     </depends>
   </mbean>
</server> 
Es wird eine MBean vom Typ org.jboss.security.auth.login.DynamicLoginConfig deklariert, die wiederum eine andere MBean Namens jboss.security:service=XMLLoginConfig ansteuert die eine Login-Konfiguration aus der Datei "META-INF/login-config.xml" lädt. Siehe JBoss-Wiki:
http://wiki.jboss.org/wiki/Wiki.jsp?page=DynamicLoginConfig und http://wiki.jboss.org/wiki/Wiki.jsp?page=LoginConfiguration. Die MBean wird unter dem Service-Namen jboss:service=DynamicLoginConfig registriert.

login-config.xml deklariert die Referenz auf unser Login-Modul.
<?xml version='1.0'?>
<!DOCTYPE policy PUBLIC
      "-//JBoss//DTD JBOSS Security Config 3.0//EN"
      "http://www.jboss.org/j2ee/dtd/security_config.dtd">
<policy>
    <application-policy name = "knaufsecurity">
       <authentication>
          <login-module code = "de.fhw.swtvertiefung.knauf.security.loginmodule.KundeAdministratorLoginModule"
             flag = "required">
             <module-option name = "DATASOURCE_JNDI">java:/DefaultDS</module-option>
             <module-option name = "DBSCHEMA">PUBLIC</module-option>
          </login-module>
       </authentication>
    </application-policy>
</policy> 
Wir vergeben eine "application-policy" für die dieses Login-Modul dient (diese wird später als "Security Domain" in den einzelnen Projekten auftauchen). Als "login-module" dient unsere Klasse. Zwei Config-Parameter müssen als "module-option" übergeben werden.

Leider hilft uns hier der WebTools-Plugin nicht beim Erzeugen der SAR-Datei, und auch das Kopieren zum Server muss anders geschehen.
Deshalb bedienen wir uns des Build-Tools "Ant", dass in Eclipse integriert ist.
Wir legen im Projekt eine Datei "build.xml" mit diesem Inhalt an:
<!-- Build script für "securityloginmodule.sar"-->
<project name="SecurityLoginModule" default="securityloginmodule">
    <property name="src.root"    value="src"/>
    <property name="meta-inf"    value="meta-inf"/>
    <property name="build.dir"   value="bin" />
    <property name="build.classes.dir" value="${build.dir}" />

    <target name="securityloginmodule">
        <jar jarfile="${build.dir}/securityloginmodule.sar">
            <metainf dir="${meta-inf}" includes="jboss-service.xml"/>
            <metainf dir="${meta-inf}" includes="login-config.xml"/>
            <fileset dir="${build.classes.dir}">
                <include name="de/fhw/swtvertiefung/knauf/security/loginmodule/*"/>
            </fileset>
        </jar>
    </target>
</project> 
Es werden vier Variablen ("src.root", "meta-inf", "build.dir" und "build.classes.dir") deklariert, die Pfade zu verschiedenen Teilen des Projekts deklarieren. Anschließend wird ein Build-Job "securityloginmodule" deklariert, der eine JAR-Datei "securityloginmodule.sar" erzeugt und aus den Unteraufgaben "jboss-service.xml ins Verzeichnis meta-inf packen", "login-config.xml ins Verzeichnis meta-inf packen" und "alle .class-Dateien packen" besteht.
Öffnen wir die Datei per Doppelklick, erscheint in der "Outline View" eine Baumstruktur der Datei, und per Rechtsklick können wir die einzelnen Ant-Tasks aufrufen.
Ant-Task

Jetzt können wir die erzeugte SAR-Datei (liegt im Verzeichnis "bin" des Projekts) in das Deploy-Verzeichnis des JBoss kopieren (muss per Hand geschehen).
Rufen wir die JMX-Console auf, finden wir unsere DynamicLoginConfig-MBean hier:
DynamicLoginConfig-MBean (1)
In den Details finden wir unsere Angaben aus "jboss-service.xml" wieder:
DynamicLoginConfig-MBean (2)


EJB-Projekt

Jetzt wird das EJB-Projekt fertiggestellt.
Wir legen eine Entitiy-Bean "StudentBean" an, mit den Datenbankfeldern "ID", "LOGIN", "NAME" und "PASSWORT".
Die XDoclet-Tags im Bean-Header sehen so aus:
 * @ejb.bean name="Kunde"  
 *           description="Ein Kunde"
 *           display-name="Kunde"
 *           jndi-name="Kunde"
 *           type="CMP" 
 *           transaction-type="Container"
 *           cmp-version="2.x" 
 *           view-type="local" 
 *           primkey-field="id"
 * @ejb.persistence  
 *           table-name="KUNDE" 
 * @ejb.pk 
 *           class="java.lang.Integer" 
 *           generate="false"   
Neu ist hier dass der Tabellenname im Tag @ejb.persistence direkt angegeben ist. Diese Information taucht in "jbosscmp-jdbc.xml" wieder auf.
Die Felder "ID" und "NAME" sind so deklariert:
  /**Abrufen der Kunde-ID
   * @return Die Kunde-ID
   * 
   * @ejb.persistence column-name="id"  
   * @ejb.interface-method view-type="local"
   * @ejb.pk-field
   */
  public abstract Integer getId();
  
  /**Setzen der Kunde-ID.
   * @param int_Id Die neue ID.
   * 
   * @ejb.persistence column-name="id" 
   * @ejb.interface-method view-type="local"
   * @ejb.pk-field
   */
  public abstract void setId (Integer int_Id);
  

  /**Abrufen des Kunde-Namens.
   * @return der Kunde-Name.
   * 
   * @ejb.persistence column-name="name" sql-type="VARCHAR" 
   * @ejb.interface-method view-type="local"
   */
  public abstract String getName();

  /**Setzen des Kunde-Namens.
   * @param str_Name der Name
   * 
   * @ejb.persistence column-name="name" sql-type="VARCHAR" 
   * @ejb.interface-method view-type="local"
   */
  public abstract void setName (String str_Name); 
Die getter/setter für Login und Passwort sehen identisch aus.
Wichtig ist dass hier ein korrektes Mapping auf die Spalten der bereits vorhandenen Tabellen erfolgt !


Jetzt fügen wir eine Stateless Session Bean SecuredBean im Package de.fhw.swtvertiefung.knauf.security zu. Ihre XDoclet-Deklarationen sind reichlich trivial: wir benötigen ein Remote Interface, sonst keine Besonderheiten.
 * @ejb.bean name="Secured" 
 *           description="Eine Session Bean für die Security aktiv ist."
 *           display-name="Secured"
 *           jndi-name="Secured"
 *           type="Stateless" 
 *           transaction-type="Container"
 *           view-type="remote" 
Interessanter sind die drei Geschäftsmethoden, die allesamt nichts machen, aber für unterschiedliche Rollen freigegeben sind:
  /**@ejb.create-method view-type="remote"
   * @ejb.permission unchecked="true" 
   */
  public void ejbCreate()
  {
  }

  /**Diese Methode darf nur vom Admin aufgerufen werden !
   * 
   * @ejb.interface-method view-type="remote"
   * @ejb.permission role-name="administrator" 
   */
  public void forAdminOnly()
  {
  }

  /**Diese Methode darf nur vom Student aufgerufen werden !
   * @ejb.interface-method view-type="remote"
   * @ejb.permission role-name="kunde" 
   *
   */
  public void forKundeOnly()
  {
  }

  /**Diese Methode darf von Admin und Student aufgerufen werden !
   * 
   * @ejb.interface-method view-type="remote"
   * @ejb.permission role-name="administrator,kunde" 
   */
  public void forBoth()
  {
  } 
Wichtig ist hier dass auch die ejbCreate-Methode eine Permission erhält, da ein Client sie sonst nicht aufrufen darf (es gibt eine Exception, weil alle Methoden einer Bean mit Permission-Deklarationen versehen sein müssen wenn eine dies ist).

Als letzter Schritt muss die Merge-Datei "jboss-security.xml" für XDoclet im Verzeichnis "ejbModule\META-INF" zugefügt werden, Sie enthält die Deklaration der JBoss-spezifischen Security-Angaben, in diesem Fall die Deklaration der Security-Domain. Diese muss identisch sein mit der in "login-config.xml" im LoginModul deklarierten Domain.

<security-domain>java:/jaas/knaufsecurity</security-domain>

Diese Deklaration taucht als erstes Element in "jboss.xml" auf.


Web-Projekt

Das Web-Projekt muss das EJB-Projekt referenzieren.

Zuallererst einmal legen wir ein Servlet an, das hier keine Funktion hat, aber dazu dient ein paar XDoclet-Deklarationen zu übernehmen ;-). Dieses Servlet kommt mal wieder in das Package de.fhw.swtvertiefung.knauf.security und heißt DummyServlet. Ansonsten verwenden wir es überhaupt nicht mehr.
Jetzt legen wir im Verzeichnis "WebContent\WEB-INF" zwei Merge-Dateien für XDoclet an:
"web-security.xml" enthält die Security-Konfiguration für unser Projekt:
	<security-constraint>
		<display-name>
		Security Constraint für SecurityWeb</display-name>
		<web-resource-collection>
			<web-resource-name>Alles</web-resource-name>
			<url-pattern>/*</url-pattern>
			<http-method>GET</http-method>
			<http-method>POST</http-method>
		</web-resource-collection>
		<auth-constraint>
			<description>
			Administrator und Kunde dürfen auf diese Seite zugreifen</description>
			<role-name>administrator</role-name>
			<role-name>kunde</role-name>
		</auth-constraint>
	</security-constraint>
	<login-config>
		<auth-method>FORM</auth-method>
		<form-login-config>
			<form-login-page>/login.jsp</form-login-page>
			<form-error-page>/error.jsp</form-error-page>
		</form-login-config>
	</login-config>
	<security-role>
		<description>Administrator im Web</description>
		<role-name>administrator</role-name>
	</security-role>
	<security-role>
		<description>Kunde im Web</description>
		<role-name>kunde</role-name>
	</security-role>
Ab jetzt wird sich der XML Validator über diese Datei beschweren da es sich um ungültiges XML handelt. Leider können wir da nichts machen...

Außerdem wird eine Datei "web-ejbrefs.xml" angelegt die die benötigten EJB-Referenzen enthält (dies wäre auch über @web.ejb-ref-XDoclet-Tags in der Servlet-Klasse gegangen):
   <ejb-ref >
      <ejb-ref-name>ejb/Secured</ejb-ref-name>
      <ejb-ref-type>Session</ejb-ref-type>
      <home>de.fhw.swtvertiefung.knauf.security.SecuredHome</home>
      <remote>de.fhw.swtvertiefung.knauf.security.Secured</remote>
      <ejb-link>Secured</ejb-link>
   </ejb-ref> 
Jetzt werden noch drei JSP-Dateien zugefügt: "index.jsp" ruft die drei Methoden der SecuredBean auf. "error.jsp" dient als Fehlerseite bei Anmeldefehlern. Und "login.jsp" ist unser Login-Formular und entspricht haargenau dem WebSphere-Beispiel:
   <form method="post" ACTION="j_security_check">
      Login: <input type="text" name="j_username" /> <br>
      Passwort: <input type="password" name="j_password" /> <br>
      <input type="submit" name="login" value="Login">
   </form> 

Der Logout-Button in "index.jsp" muss hier zu einer selbstgebauten Seite führen da es im Gegensatz zum WebSphere keine Standard-Logout-Aktion gibt.
   <FORM METHOD=POST ACTION="logout.jsp" NAME="logout">
      <input type="submit" name="logout" value="Logout">
   </FORM> 
Die Seite "logout.jsp" sieht im Kern so aus:
  <%
    //Session beenden:
    session.invalidate(); 
  %>
  <P>Sie wurden abgemeldet ! </P>
  <a href="index.jsp">Zurück zur Startseite</a> 

ACHTUNG: Der folgende Abschnitt gilt nicht mehr für WTP 1.5.1, dort gibt es eine XDoclet-Property "Security Domain", kein Tricksen mit Ant-Scripten mehr !

Jetzt müssen wir "nur" noch einen letzten Ringkampf mit XDoclet ausfechten: wie im EJB-Projekt müssen wir die JBoss-Security-Domain deklarieren. Konsequenterweise geht das hier aber anders als im EJB-Projekt (keine Merge-Datei sondern ein Attribut des XDoclet-Subtasks "jbosswebxml"). Dieses Attribut ist nicht im WebTools-Plugin konfigurierbar, deshalb müssen wir die Ant-Build-Datei "tempAnt.xml" und die zugehörige Config-Datei "build.properties" per Hand aus "%WORKSPACE%\.metadata\.plugins\org.eclipse.jst.j2ee.ejb.annotations.xdoclet" ins Projekt kopieren. Wichtig hierbei: wenn sich an der "echten" Build-Datei etwas ändert (z.B. weil neue Subtasks hinzukommen) müssen wir sie natürlich neu kopieren. Nach einem Import auf einen Rechner mit anderen Pfaden müssen wir build.properties ebenfalls neu aus dem Workspace heraus ziehen. Das Kopieren MUSS erfolgen direkt nachdem ein Build des Webprojekts erfolgte da die Dateien sonst z.B. von der Build-Datei des EJB-Projekts überschrieben werden :-(.
Hier gibt es den Bug dazu:
https://bugs.eclipse.org/bugs/show_bug.cgi?id=121853.
In der so kopierten Datei "tempAnt.xml" ändern wir das Element "jbosswebxml" und fügen den fetten Teil zu:

<jbosswebxml version="4.0" contextroot="${web}" securitydomain="java:/jaas/knaufsecurity" xmlencoding="UTF-8" validatexml="false" mergedir="${web.dd.dir}" destdir="${web.dd.dir}" />

Wenn wir diese Datei per Doppelklick öffnen sehen wir in der "Outline" die verfügbaren Build Targets. Wir führen jeweils "webdoclet" aus.
Ant-Task webdoclet
Dieser Aufruf muss nach dem jedem Build erfolgen, bei dem der Standard-XDoclet-Task zuschlägt und "jboss-web.xml" überschreibt. Also auf jeden Fall vor einem Publish !
Um unser Glück vollständig zu machen kommt nach einem solchen Ant-Aufruf und einem anschließenden Publish-Versuch die Meldung "Resource is out of sync with the file system: /SecurityWeb/WebContent/WEB-INF/web.xml." (dito für "jboss-web.xml"). Lösung: Ein Refresh auf dem Web-Projekt ausführen.

Unsere schicke Anwendung ist jetzt unter http://localhost:8080/SecurityWeb erreichbar und sollte uns mit dem Login-Formular beglücken.


Application Client-Projekt

Das Application Client Project muss das EJB-JAR referenzieren.
Die Klasse de.fhw.swtvertiefung.knauf.security.SecurityClient wird zugefügt. In der Main-Methode geschehen die Aufrufe der SecuredBean.
In "application-client.xml" muss eine EJB-Referenz auf SecuredBean eingetragen werden:
<?xml version="1.0" encoding="UTF-8"?>
<application-client id="Application-client_ID" version="1.4" 
	xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/application-client_1_4.xsd">
	<display-name>SecurityClient</display-name>
	<ejb-ref>
		<ejb-ref-name>ejb/Secured</ejb-ref-name>
		<ejb-ref-type>Session</ejb-ref-type>
		<home>de.fhw.swtvertiefung.knauf.security.SecuredHome</home>
		<remote>de.fhw.swtvertiefung.knauf.security.Secured</remote>
		<ejb-link>Secured</ejb-link>
	</ejb-ref>
</application-client> 

Das Kernproblem des ApplicationClient ist es, die Security-Informationen zu erfassen und zum Server zu bringen. Zuerst einmal muss eine Anmeldekonfiguration angelegt werden. Dazu legen wir im Unterverzeichnis "appClientModule/META-INF" eine Datei "auth.conf" mit diesem Inhalt an:
knaufclientsecurity {
   // jBoss LoginModule
   org.jboss.security.ClientLoginModule  required
   ;
}; 
Mit dieser Datei wird festgelegt dass für die Anwendung eine SecurityDomäne "knaufclientsecurity" existiert, als LoginModul dient org.jboss.security.ClientLoginModule.

Eine Klasse muss implementiert werden die die Security-Informationen von der Client-Anwendung anfordert und an den Server übergibt. Hierzu muss das Interface javax.security.auth.callback.CallbackHandler implementiert werden. Dessen Methode handle (Callback[] callbacks) wird vom Server aufgerufen, das übergebene Array von Callbacks beschreibt die angeforderten Informationen (die in den entsprechenden Callback geschrieben werden).
Der Code sieht (gekürzt) so aus:
public class SecurityClientCallbackHandler implements CallbackHandler
{
  public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
  {
    //Über alle übergebenen Callbacks iterieren:
    for (int intIndexCallback = 0; intIndexCallback < callbacks.length; intIndexCallback++)
    {
      //NameCallback: Login übergeben.
      if (callbacks[intIndexCallback] instanceof NameCallback)
      {
        NameCallback nameCallback = (NameCallback) callbacks[intIndexCallback];
        nameCallback.setName( "ADMIN" );
      }
      //PasswordCallback: Login übergeben.
      else if (callbacks[intIndexCallback] instanceof PasswordCallback)
      {
        PasswordCallback passwordCallback = (PasswordCallback) callbacks[intIndexCallback];
        passwordCallback.setPassword ("ADMIN".toCharArray() );
      }
      else
      {
        throw new UnsupportedCallbackException (callbacks[intIndexCallback], "Nicht unterstützer Callback !");
      }
    }
  }
}
Die Vorbereitungen sind getroffen, jetzt können wir den Client erstellen. Die Initialisierung sieht so aus:
      Properties props = new Properties();
      props.setProperty(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
      props.setProperty(Context.URL_PKG_PREFIXES, "org.jboss.naming.client");
      props.setProperty(Context.PROVIDER_URL, "jnp://localhost:1099");
      props.setProperty("j2ee.clientName", "SecurityClient");
      
      InitialContext initialContext = new InitialContext(props);
      
      //Login initialisieren:
      SecurityClientCallbackHandler callbackHandler = new SecurityClientCallbackHandler();
      LoginContext loginContext = new LoginContext ("knaufclientsecurity", callbackHandler);
      loginContext.login(); 
Wichtig ist hier die Initialisierung des LoginContexts, dem eine Instanz unseres CallbackHandlers übergeben wird. Als Name des LoginContexts muss der gleiche Wert angegeben sein der auch in "auth.conf" steckt !

Ab jetzt können wir die Beans aufrufen.

Beim Start des Clients ist zu beachten dass wir die Datei "auth.conf" in einem Java-Parameter java.security.auth.login.config übergeben müssen. Deshalb muss für den Client eine "Run Configuration" angelegt werden.
Im Menü "Run" den Punkt "Run..." wählen. Links unter "Java Application" eine neue namens "SecurityClient" zufügen. Auf der Karteikarte "Main" wird de.fhw.swtvertiefung.knauf.security.SecurityClient als "Main class" gewählt. Auf der Karteikarte "Arguments" wird das Argument -Djava.security.auth.login.config=appClientModule/META-INF/auth.conf eingetragen:
Run Application Client



Version 1.0.0.1, Stand 07.09.2006
Historie:
1.0.0.0 (29.12.2005): Erstellt
1.0.0.1 (15.01.2006): Code im Login-Modul aufgeräumt (Kommentare).
07.09.2006: Hinweis auf XDoclet-Feature "Security Domain"