Programmierung der Clientauthentifizierung

Für die Authentifizierung stellt WebSphere eXtreme Scale eine Laufzeitumgebung bereit, in der der Berechtigungsnachweis vom Client an die Serverseite gesendet und anschließend das Authenticator-Plug-in für die Authentifizierung der Benutzer aufgerufen wird.

WebSphere eXtreme Scale setzt die Implementierung der folgenden Plug-ins für die Durchführung der Authentifizierung voraus.

Credential- und CredentialGenerator-Plug-ins

Wenn ein eXtreme-Scale-Client eine Verbindung zu einem Server herstellt, der eine Authentifizierung voraussetzt, muss der Client einen Clientberechtigungsnachweis vorlegen. Ein Clientberechtigungsnachweis wird durch eine Schnittstelle "com.ibm.websphere.objectgrid.security.plugins.Credential" dargestellt. Gültige Clientberechtigungsnachweise sind eine Kombination von Benutzername und Kennwort, ein Kerberos-Ticket, ein Clientzertifikat oder Daten in einem beliebigen Format, auf das sich Client und Server geeinigt haben. Diese Schnittstelle definiert explizit die Methoden "equals(Object)" und "hashCode". Diese beiden Methoden sind wichtig, weil die authentifizierten Subject-Objekte mit dem Credential-Objekt als Schlüssel auf der Serverseite zwischengespeichert werden. WebSphere eXtreme Scale stellt auch ein Plug-in für die Generierung eines Berechtigungsnachweises bereit. Dieses Plug-in wird durch die Schnittstelle "com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator" dargestellt und ist hilfreich, wenn der Berechtigungsnachweis eine Verfallszeit haben kann. In diesem Fall wird die Methode "getCredential" aufgerufen, um einen Berechtigungsnachweis zu erneuern.

Die Schnittstelle "Credential" definiert explizit die Methoden "equals(Object)" und "hashCode". Diese beiden Methoden sind wichtig, weil die authentifizierten Subject-Objekte mit dem Credential-Objekt als Schlüssel auf der Serverseite zwischengespeichert werden.

Sie können das bereitgestellte Plug-in verwenden, um einen Berechtigungsnachweis zu erstellen. Dieses Plug-in wird durch die Schnittstelle "com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator" dargestellt und ist hilfreich, wenn der Berechtigungsnachweis eine Verfallszeit haben kann. In diesem Fall wird die Methode "getCredential" aufgerufen, um einen Berechtigungsnachweis zu erneuern. Weitere Informationen finden Sie in Schnittstelle "CredentialGenerator" .

Es werden drei Standardimplementierungen für die Schnittstelle "Credential" bereitgestellt:

  • Die Implementierung "com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredential" enthält eine Kombination von Benutzer-ID und Kennwort.
  • Die Implementierung "com.ibm.websphere.objectgrid.security.plugins.builtins.WSTokenCredential" enthält spezielle Authentifizierungs- und Berechtigungstoken für WebSphere Application Server. Diese Token können verwendet werde, um die Sicherheitsattribute an die Anwendungsserver in derselben Sicherheitsdomäne weiterzugeben.

WebSphere eXtreme Scale stellt auch ein Plug-in für die Generierung eines Berechtigungsnachweises bereit. Dieses Plug-in wird durch die Schnittstelle "com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator" dargestellt. WebSphere eXtreme Scale stellt zwei integrierte Standardimplementierungen bereit:

  • Der Konstruktor com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredentialGenerator akzeptiert eine Benutzer-ID und ein Kennwort. Beim Aufruf der Methode "getCredential" wird ein UserPasswordCredential-Objekt zurückgegeben, das die Benutzer-ID und das Kennwort enthält.
  • Die Implementierung com.ibm.websphere.objectgrid.security.plugins.builtins.WSTokenCredentialGenerator stellt einen Berechtigungsnachweisgenerator (bzw. Sicherheitstokengenerator) dar, wenn Sie mit WebSphere Application Server arbeiten. Beim Aufruf der Methode "getCredential" wird das Subject-Objekt abgerufen, das dem aktuellen Thread zugeordnet ist. Anschließend werden die Sicherheitsinformationen in diesem Subject-Objekt in ein WSTokenCredential-Objekt konvertiert. Sie können angeben, ob mit der Konstanten "WSTokenCredentialGenerator.RUN_AS_SUBJECT" oder "WSTokenCredentialGenerator.CALLER_SUBJECT" ein RunAs-Subject- oder ein Caller-Subject-Objekt vom Thread abgerufen werden soll.

UserPasswordCredential und UserPasswordCredentialGenerator

Für Testzwecke stellt WebSphere eXtreme Scale die folgenden Plug-in-Implementierungen bereit:

  1. com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredential
  2. com.ibm.websphere.objectgrid.security.plugins.builtins.UserPasswordCredentialGenerator

Das UserPasswordCredential enthält eine Benutzer-ID und ein Kennwort. Der Der UserPasswordCredentialGenerator speichert diese Benutzer-ID und dieses Kennwort anschließend.

Der folgende Beispielcode veranschaulicht, wie diese beiden Plug-ins implementiert werden.

UserPasswordCredential.java
// Dieses Beispielprogramm wird ohne Wartung (auf "as-is"-Basis)
// bereitgestellt und kann vom Kunden (a) zu Schulungs- und Studienzwecken,
// (b) zum Entwickeln von Anwendungen für ein IBM WebSphere-Produkt zur
// internen Nutzung beim Kunden oder Weitergabe im Rahmen einer solchen
// Anwendung in kundeneigenen Produkten gebührenfrei genutzt, ausgeführt,
// kopiert und geändert werden.
// Lizenziertes Material - Eigentum von IBM
// 5724-J34 © COPYRIGHT International Business Machines Corp. 2007
package com.ibm.websphere.objectgrid.security.plugins.builtins;

import com.ibm.websphere.objectgrid.security.plugins.Credential;

/**
 * This class represents a credential containing a user ID and password.
 *
 * @ibm-api
 * @since WAS XD 6.0.1
 *
 * @see Credential
 * @see UserPasswordCredentialGenerator#getCredential()
 */
public class UserPasswordCredential implements Credential {

    private static final long serialVersionUID = 1409044825541007228L;

    private String ivUserName;

    private String ivPassword;

    /**
     * Creates a UserPasswordCredential with the specified user name and
     * password.
     *
     * @param userName the user name for this credential
     * @param password the password for this credential
     *
     * @throws IllegalArgumentException if userName or password is <code>null</code>
     */
    public UserPasswordCredential(String userName, String password) {
        super();
        if (userName == null || password == null) {
            throw new IllegalArgumentException("User name and password cannot be null.");
        }
        this.ivUserName = userName;
        this.ivPassword = password;
    }

    /**
     * Gets the user name for this credential.
     *
     * @return   the user name argument that was passed to the constructor
     *           or the <code>setUserName(String)</code>
     *           method of this class
     *
     * @see #setUserName(String)
     */
    public String getUserName() {
        return ivUserName;
    }

    /**
     * Sets the user name for this credential.
     *
     * @param userName the user name to set.
     *
     * @throws IllegalArgumentException if userName is <code>null</code>
     */
    public void setUserName(String userName) {
        if (userName == null) {
            throw new IllegalArgumentException("User name cannot be null.");
        }
        this.ivUserName = userName;
    }

    /**
     * Gets the password for this credential.
     *
     * @return   the password argument that was passed to the constructor
     *           or the <code>setPassword(String)</code>
     *           method of this class
     *
     * @see #setPassword(String)
     */
    public String getPassword() {
        return ivPassword;
    }

    /**
     * Sets the password for this credential.
     *
     * @param password the password to set.
     *
     * @throws IllegalArgumentException if password is <code>null</code>
     */
    public void setPassword(String password) {
        if (password == null) {
            throw new IllegalArgumentException("Password cannot be null.");
        }
        this.ivPassword = password;
    }

    /**
     * Checks two UserPasswordCredential objects for equality.
     * <p>
     * Two UserPasswordCredential objects are equal if and only if their user names
     * and passwords are equal.
     *
     * @param o the object we are testing for equality with this object.
     *
     * @return <code>true</code> if both UserPasswordCredential objects are equivalent.
     *
     * @see Credential#equals(Object)
     */
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o instanceof UserPasswordCredential) {
            UserPasswordCredential other = (UserPasswordCredential) o;
            return other.ivPassword.equals(ivPassword) && other.ivUserName.equals(ivUserName);
        }

        return false;
    }

    /**
     * Returns the hashcode of the UserPasswordCredential object.
     *
     * @return the hash code of this object
     *
     * @see Credential#hashCode()
     */
    public int hashCode() {
        return ivUserName.hashCode() + ivPassword.hashCode();
    }
}
UserPasswordCredentialGenerator.java
// Dieses Beispielprogramm wird ohne Wartung (auf "as-is"-Basis)
// bereitgestellt und kann vom Kunden (a) zu Schulungs- und Studienzwecken,
// (b) zum Entwickeln von Anwendungen für ein IBM WebSphere-Produkt zur
// internen Nutzung beim Kunden oder Weitergabe im Rahmen einer solchen
// Anwendung in kundeneigenen Produkten gebührenfrei genutzt, ausgeführt,
// kopiert und geändert werden.
// Lizenziertes Material - Eigentum von IBM
// 5724-J34 © COPYRIGHT International Business Machines Corp. 2007
package com.ibm.websphere.objectgrid.security.plugins.builtins;

import java.util.StringTokenizer;

import com.ibm.websphere.objectgrid.security.plugins.Credential;
import com.ibm.websphere.objectgrid.security.plugins.CredentialGenerator;

/**
 * This credential generator creates <code>UserPasswordCredential</code> objects.
 * <p>
 * UserPasswordCredentialGenerator has a one to one relationship with
 * UserPasswordCredential because it can only create a UserPasswordCredential
 * representing one identity.
 *
 * @since WAS XD 6.0.1
 * @ibm-api
 *
 * @see CredentialGenerator
 * @see UserPasswordCredential
 */
public class UserPasswordCredentialGenerator implements CredentialGenerator {

    private String ivUser;

    private String ivPwd;

    /**
     * Creates a UserPasswordCredentialGenerator with no user name or password.
     *
     * @see #setProperties(String)
     */
    public UserPasswordCredentialGenerator() {
        super();
    }

    /**
     * Creates a UserPasswordCredentialGenerator with a specified user name and
     * password
     *
     * @param user the user name
     * @param pwd the password
     */
    public UserPasswordCredentialGenerator(String user, String pwd) {
        ivUser = user;
        ivPwd = pwd;
    }

    /**
     * Creates a new <code>UserPasswordCredential</code> object using this
     * object's user name and password.
     *
     * @return a new <code>UserPasswordCredential</code> instance
     *
     * @see CredentialGenerator#getCredential()
     * @see UserPasswordCredential
     */
    public Credential getCredential() {
        return new UserPasswordCredential(ivUser, ivPwd);
    }

    /**
     * Gets the password for this credential generator.
     *
     * @return   the password argument that was passed to the constructor
     */
    public String getPassword() {
        return ivPwd;
    }

    /**
     * Gets the user name for this credential.
     *
     * @return   the user argument that was passed to the constructor
     *           of this class
     */
    public String getUserName() {
        return ivUser;
    }
    /**
     * Sets additional properties namely a user name and password.
     *
     * @param properties a properties string  with a user name and
     *                   a password separated by a blank.
     *
     * @throws IllegalArgumentException if the format is not valid
     */
    public void setProperties(String properties) {
        StringTokenizer token = new StringTokenizer(properties, " ");
        if (token.countTokens() != 2) {
            					throw new IllegalArgumentException(
                "The properties should have a user name and password and separated by a blank.");
        }

        ivUser = token.nextToken();
        ivPwd = token.nextToken();
    }
    /**
     * Checks two UserPasswordCredentialGenerator objects for equality.
     * <p>
     * Two UserPasswordCredentialGenerator objects are equal if and only if
     * their user names and passwords are equal.
     *
     * @param obj the object we are testing for equality with this object.
     *
     * @return <code>true</code> if both UserPasswordCredentialGenerator objects
     *         are equivalent.
     */
    public boolean equals(Object obj) {
        if (obj == this) {
            return true;
        }

        if (obj != null && obj instanceof UserPasswordCredentialGenerator) {
            UserPasswordCredentialGenerator other = (UserPasswordCredentialGenerator) obj;

            boolean bothUserNull = false;
            boolean bothPwdNull = false;

            if (ivUser == null) {
                if (other.ivUser == null) {
                    bothUserNull = true;
                } else {
                    return false;
                }
            }

            if (ivPwd == null) {
                if (other.ivPwd == null) {
                    bothPwdNull = true;
                } else {
                    return false;
                }
            }

            return (bothUserNull || ivUser.equals(other.ivUser)) && (bothPwdNull || ivPwd.equals(other.ivPwd));
        }

        return false;
    }

    /**
     * Returns the hashcode of the UserPasswordCredentialGenerator object.
     *
     * @return the hash code of this object
     */
    public int hashCode() {

        return ivUser.hashCode() + ivPwd.hashCode();
    }

}

Die Klasse "UserPasswordCredential" enthält zwei Attribute: den Benutzernamen und das Kennwort. Die Klasse "UserPasswordCredentialGenerator" dient als Factory, die die UserPasswordCredential-Objekte enthält.

WSTokenCredential und WSTokenCredentialGenerator

Wenn Clients und Server von WebSphere eXtreme Scale alle in WebSphere Application Server implementiert sind, kann die Clientanwendung diese beiden integrierten Implementierungen verwenden, wenn die folgenden Bedingungen erfüllt sind:

  1. Die globale Sicherheit von WebSphere Application Server ist aktiviert.
  2. Alle eXtreme-Scale-Clients und -Server werden in JVMs von WebSphere Application Server ausgeführt.
  3. Alle Anwendungsserver befinden sich in derselben Sicherheitsdomäne.
  4. Der Client ist bereits in WebSphere Application Server authentifiziert.

In dieser Situation kann der Client die Klasse com.ibm.websphere.objectgrid.security.plugins.builtins.WSTokenCredentialGenerator verwenden, um einen Berechtigungsnachweis zu generieren. Der Server verwendet die WSAuthenticator-Implementierungsklasse, um den Berechtigungsnachweis zu authentifizieren.

In diesem Szenario wird die Tatsache genutzt, dass der eXtreme-Scale-Client bereits authentifiziert wurde. Da sich die Anwendungsserver, die Server haben, in derselben Sicherheitsdomäne wie die Anwendungsserver befinden, die Clients haben, können die Sicherheitstoken vom Client an den Server weitergegeben werden, so dass dieselbe Benutzerregistry nicht erneut authentifiziert werden muss.

Anmerkung: Gehen Sie nicht davon aus, dass ein CredentialGenerator immer denselben Berechtigungsnachweis generiert. Für ein Berechtigungsnachweis mit Verfallszeit und aktualisierbare Berechtigungsnachweise sollte der CredentialGenerator in der Lage sein, einen aktuellen gültigen Berechtigungsnachweis zu generieren, um sicherzustellen, dass die Authentifizierung erfolgreich ist. Ein Beispiel ist die Verwendung des Kerberos-Tickets als Credential-Objekt. Wenn das Kerberos-Ticket aktualisiert wird, muss der CredentialGenerator das aktualisierte Ticket abrufen, wenn CredentialGenerator.getCredential aufgerufen wird.

Authenticator-Plug-in

Nachdem der eXtreme-Scale-Client das Credential-Objekt mit dem CredentialGenerator-Objekt abgerufen hat, wird dieses Client-Credential-Objekt zusammen mit der Clientanforderung an den eXtreme-Scale-Server gesendet. Der Server authentifiziert das Credential-Objekt, bevor er die Anforderung verarbeitet. Bei erfolgreicher Authentifizierung des Credential-Objekts wird ein Subject-Objekt zurückgegeben, das diesen Client repräsentiert.

Dieses Subject-Objekt wird zwischengespeichert und verfällt erst, wenn seine Lebensdauer das festgelegte Sitzungszeitlimit erreicht. Das Zeitlimit für die Anmeldesitzung kann mit der Eigenschaft "loginSessionExpirationTime" in der XML-Datei des Clusters definiert werden. Wenn Sie beispielsweise loginSessionExpirationTime="300" definieren, verfällt das Subject-Objekt nach 300 Sekunden.

Dieses Subject-Objekt wird anschließend für die Berechtigung der Anforderung verwendet, was später noch erläutert wird. Ein eXtreme-Scale-Server verwendet das Authenticator-Plug-in, um das Credential-Objekt zu authentifizieren. Weitere Einzelheiten finden Sie in Authenticator .

Im Authenticator-Plug-in authentifiziert die Laufzeitumgebung von eXtreme Scale das Credential-Objekt aus der Benutzerregistry des Clients, z. B. einem LDAP-Server.

WebSphere eXtreme Scale stellt keine sofort einsatzfähige Benutzerregistrykonfiguration bereit. Die Konfiguration und Verwaltung der Benutzerregistry erfolgt aus Gründen der Einfachheit und Flexibilität außerhalb von WebSphere eXtreme Scale. Dieses Plug-in implementiert die Verbindungsherstellung zur und die Authentifizierung über die Benutzerregistry. Eine Authenticator-Implementierung extrahiert beispielsweise die Benutzer-ID und das Kennwort aus dem Berechtigungsnachweis, verwendet diese Informationen für die Herstellung einer Verbindung zu einem und Validierung bei einem LDAP-Server und erstellt als Ergebnis der Authentifizierung ein Subject-Objekt. Die Implementierung kann JAAS-Anmeldemodule verwenden. Als Ergebnis der Authentifizierung wird ein Subject-Objekt zurückgegeben.

Beachten Sie, dass diese Methode zwei Ausnahmen erstellt: InvalidCredentialException und ExpiredCredentialException. Die Ausnahme "InvalidCredentialException" zeigt an, dass der Berechtigungsnachweis nicht gültig ist. Die Ausnahme "ExpiredCredentialException" zeigt an, dass der Berechtigungsnachweis abgelaufen ist. Wenn eine dieser Ausnahmen in der Methode "authenticate" eintritt, wird sie an den Client zurückgesendet. Die Laufzeitumgebung des Clients behandelt diese Ausnahmen jedoch auf unterschiedliche Weise:

  • Wenn der Fehler eine Ausnahme "InvalidCredentialException" ist, zeigt die Laufzeitumgebung des Clients diese Ausnahme an. Ihre Anwendung muss die Ausnahme behandeln. In diesem Fall können Sie den CredentialGenerator beispielsweise korrigieren und die Operation anschließend wiederholen.
  • Wenn der Fehler eine Ausnahme "ExpiredCredentialException" ist und der Wiederholungszähler nicht 0 ist, ruft die Laufzeitumgebung des Clients die Methode "CredentialGenerator.getCredential" erneut auf und sendet das neue Credential-Objekt an den Server. Wenn die Authentifizierung des neuen Berechtigungsnachweises erfolgreich ist, verarbeitet der Server die Anforderung. Schlägt die Authentifizierung des neuen Berechtigungsnachweises fehl, wird die Ausnahme an den Client zurückgesendet. Wenn die Anzahl der Authentifizierungswiederholungen den unterstützten Wert erreicht und der Client immer noch eine Ausnahme "ExpiredCredentialException" empfängt, wird die Ausnahme "ExpiredCredentialException" ausgelöst. Ihre Anwendung muss den Fehler behandeln.

Die Schnittstelle "Authenticator" bietet hohe Flexibilität. Sie können die Schnittstelle "Authenticator" auf Ihre eigene spezielle Weise implementieren. Sie können diese Schnittstelle beispielsweise für die Unterstützung von zwei unterschiedlichen Benutzerregistrys implementieren.

WebSphere eXtreme Scale stellt Beispielimplementierungen des Authenticator-Plug-ins bereit. Mit Ausnahme des Authenicator-Plug-ins von WebSphere Application Server sind die anderen Implementierungen nur Beispiele für Testzwecke.

KeyStoreLoginAuthenticator

In diesem Beispiel wird eine integrierte eXtreme-Scale-Implementierung verwendet, die Implementierung "KeyStoreLoginAuthenticator", die für Test- und Beispielzwecke bestimmt ist (ein Keystore ist eine einfache Benutzerregistry und sollte nicht für eine Produktionsumgebung verwendet werden). Auch hier sehen Sie die Klasse, um ausführlicher zu demonstrieren, wie ein Authentifikator implementiert wird:

KeyStoreLoginAuthenticator.java
// Dieses Beispielprogramm wird ohne Wartung (auf "as-is"-Basis)
// bereitgestellt und kann vom Kunden (a) zu Schulungs- und Studienzwecken,
// (b) zum Entwickeln von Anwendungen für ein IBM WebSphere-Produkt zur
// internen Nutzung beim Kunden oder Weitergabe im Rahmen einer solchen
// Anwendung in kundeneigenen Produkten gebührenfrei genutzt, ausgeführt,
// kopiert und geändert werden.
// Lizenziertes Material - Eigentum von IBM
// 5724-J34 © COPYRIGHT International Business Machines Corp. 2007

package com.ibm.websphere.objectgrid.security.plugins.builtins;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;

import com.ibm.websphere.objectgrid.security.plugins.Authenticator;
import com.ibm.websphere.objectgrid.security.plugins.Credential;
import com.ibm.websphere.objectgrid.security.plugins.ExpiredCredentialException;
import com.ibm.websphere.objectgrid.security.plugins.InvalidCredentialException;
import com.ibm.ws.objectgrid.Constants;
import com.ibm.ws.objectgrid.ObjectGridManagerImpl;
import com.ibm.ws.objectgrid.security.auth.callback.UserPasswordCallbackHandlerImpl;

/**
 * This class is an implementation of the <code>Authenticator</code> interface
 * when a user name and password are used as a credential.
 * <p>
 * When user ID and password authentication is used, the credential passed to the
 * <code>authenticate(Credential)</code> method is a UserPasswordCredential object.
 * <p>
 * This implementation will use a <code>KeyStoreLoginModule</code> to authenticate
 * the user into the key store using the JAAS login module "KeyStoreLogin". The key
 * store can be configured as an option to the <code>KeyStoreLoginModule</code>
 * class. Please see the <code>KeyStoreLoginModule</code> class for more details
 * about how to set up the JAAS login configuration file.
 * <p>
 * This class is only for sample and quick testing purpose. Users should
 * write your own Authenticator implementation which can fit better into
 * the environment.
 *
 * @ibm-api
 * @since WAS XD 6.0.1
 *
 * @see Authenticator
 * @see KeyStoreLoginModule
 * @see UserPasswordCredential
 */
public class KeyStoreLoginAuthenticator implements Authenticator {

    /**
     * Creates a new KeyStoreLoginAuthenticator.
     */
    public KeyStoreLoginAuthenticator() {
        super();
    }

    /**
     * Authenticates a <code>UserPasswordCredential</code>.
     * <p>
     * Uses the user name and password from the specified UserPasswordCredential
     * to login to the KeyStoreLoginModule named "KeyStoreLogin".
     *
     * @throws InvalidCredentialException if credential isn't a
     *         UserPasswordCredential or some error occurs during processing
     *         of the supplied UserPasswordCredential
     *
     * @throws ExpiredCredentialException if credential is expired.  This exception
     *         is not used by this implementation
     *
     * @see Authenticator#authenticate(Credential)
     * @see KeyStoreLoginModule
     */
    public Subject authenticate(Credential credential) throws InvalidCredentialException, ExpiredCredentialException {

        if (credential == null) {
            throw new InvalidCredentialException("Supplied credential is null");
        }

        if ( ! (credential instanceof UserPasswordCredential) ) {
            throw new InvalidCredentialException("Supplied credential is not a UserPasswordCredential");
        }

        UserPasswordCredential cred = (UserPasswordCredential) credential;
        LoginContext lc = null;
        try {
            lc = new LoginContext("KeyStoreLogin",
                    new UserPasswordCallbackHandlerImpl(cred.getUserName(), cred.getPassword().toCharArray()));

            lc.login();

            Subject subject = lc.getSubject();

            return subject;
        }
        catch (LoginException le) {
            throw new InvalidCredentialException(le);
        }
        catch (IllegalArgumentException ile) {
            throw new InvalidCredentialException(ile);
        }
    }
}
KeyStoreLoginModule.java
// Dieses Beispielprogramm wird ohne Wartung (auf "as-is"-Basis)
// bereitgestellt und kann vom Kunden (a) zu Schulungs- und Studienzwecken,
// (b) zum Entwickeln von Anwendungen für ein IBM WebSphere-Produkt zur
// internen Nutzung beim Kunden oder Weitergabe im Rahmen einer solchen
// Anwendung in kundeneigenen Produkten gebührenfrei genutzt, ausgeführt,
// kopiert und geändert werden.
// Lizenziertes Material - Eigentum von IBM
// 5724-J34 © COPYRIGHT International Business Machines Corp. 2007
package com.ibm.websphere.objectgrid.security.plugins.builtins;

import java.io.File;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.UnrecoverableKeyException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import javax.security.auth.x500.X500Principal;
import javax.security.auth.x500.X500PrivateCredential;

import com.ibm.websphere.objectgrid.ObjectGridRuntimeException;
import com.ibm.ws.objectgrid.Constants;
import com.ibm.ws.objectgrid.ObjectGridManagerImpl;
import com.ibm.ws.objectgrid.util.ObjectGridUtil;

/**
 * A KeyStoreLoginModule is keystore authentication login module based on 
 * JAAS authentication.
 * <p>
 * A login configuration should provide an option "<code>keyStoreFile</code>" to 
 * indicate where the keystore file is located. If the <code>keyStoreFile</code> 
 * value contains a system property in the form, <code>${system.property}</code>,
 * it will be expanded to the value of the system property.
 * <p>
 * If an option "<code>keyStoreFile</code>" is not provided, the default keystore
 * file name is <code>"${java.home}${/}.keystore"</code>.
 * <p>
 * Here is a Login module configuration example: 
 * <pre><code>
 *    KeyStoreLogin {
 *        com.ibm.websphere.objectgrid.security.plugins.builtins.KeystoreLoginModule required
 *            keyStoreFile="${user.dir}${/}security${/}.keystore";
 *    };
 * </code></pre>
 * 
 * @ibm-api
 * @since WAS XD 6.0.1  
 * 
 * @see LoginModule
 */
public class KeyStoreLoginModule implements LoginModule {

    private static final String CLASS_NAME = KeyStoreLoginModule.class.getName();

    /** 
     * Key store file property name 
     */
    public static final String KEY_STORE_FILE_PROPERTY_NAME = "keyStoreFile";

    /**
     * Key store type. Only JKS is supported 
     */
    public static final String KEYSTORE_TYPE = "JKS";

    /**
     * The default key store file name 
     */
    public static final String DEFAULT_KEY_STORE_FILE = "${java.home}${/}.keystore";

    private CallbackHandler handler;

    private Subject subject;

    private boolean debug = false;

    private Set principals = new HashSet();

    private Set publicCreds = new HashSet();

    private Set privateCreds = new HashSet();

    protected KeyStore keyStore;

    /**
     * Creates a new KeyStoreLoginModule.
     */
    public KeyStoreLoginModule() {
    }

    /**
     * Initializes the login module.
     * 
     * @see LoginModule#initialize(Subject, CallbackHandler, Map, Map)
     */
    public void initialize(Subject sub, CallbackHandler callbackHandler,
            Map mapSharedState, Map mapOptions) {

        // initialize any configured options
        debug = "true".equalsIgnoreCase((String) mapOptions.get("debug"));

        if (sub == null)
            throw new IllegalArgumentException("Subject is not specified"); 

        if (callbackHandler == null)
            					throw new IllegalArgumentException(
            "CallbackHander is not specified"); 

        // Get the key store path
        String sKeyStorePath = (String) mapOptions
            .get(KEY_STORE_FILE_PROPERTY_NAME);

        // If there is no key store path, the default one is the .keystore
        // file in the java home directory
        if (sKeyStorePath == null) {
            sKeyStorePath = DEFAULT_KEY_STORE_FILE;
        }

        // Replace the system enviroment variable
        sKeyStorePath = ObjectGridUtil.replaceVar(sKeyStorePath);

        File fileKeyStore = new File(sKeyStorePath);

        try {
            KeyStore store = KeyStore.getInstance("JKS");
            store.load(new FileInputStream(fileKeyStore), null);

            // Save the key store
            keyStore = store;

            if (debug) {
                System.out.println("[KeyStoreLoginModule] initialize: Successfully loaded key store");
            }
        }
              catch(Exception e){
            ObjectGridRuntimeException re = new ObjectGridRuntimeException(
                    "Failed to load keystore: " + fileKeyStore.getAbsolutePath()); 
            re.initCause(e);
            if (debug) {
                System.out.println("[KeyStoreLoginModule] initialize: Key store loading failed with exception "
                        + e.getMessage());
            }
        }

        this.subject = sub;
        this.handler = callbackHandler;
    }

    /**
     * Authenticates a user based on the keystore file.
     * 
     * @see LoginModule#login()
     */
    public boolean login() throws LoginException {

        if (debug) {
            System.out.println("[KeyStoreLoginModule] login: entry");
        }

        String name = null;
        char pwd[] = null;

        if (keyStore == null || subject == null || handler == null) {
            throw new LoginException("Module initialization failed"); 
        }

        NameCallback nameCallback = new NameCallback("Username:");
        PasswordCallback pwdCallback = new PasswordCallback("Password:", false);

        try {
            handler.handle(new Callback[] { nameCallback, pwdCallback });
        }
              catch(Exception e){
            throw new LoginException("Callback failed: " + e); 
        }

        name = nameCallback.getName();
        char[] tempPwd = pwdCallback.getPassword();

        if (tempPwd == null) {
            // treat a NULL password as an empty password
            tempPwd = new char[0];
        }
        pwd = new char[tempPwd.length];
        System.arraycopy(tempPwd, 0, pwd, 0, tempPwd.length);

        pwdCallback.clearPassword();

        if (debug) {
            System.out.println("[KeyStoreLoginModule] login: "
                    + "user entered user name: " + name);
        }

        // Validate the user name and password
        try {
            validate(name, pwd);
        }
        catch (SecurityException se) {
            principals.clear();
            publicCreds.clear();
            privateCreds.clear();
            LoginException le = new LoginException(
            "Exception encountered during login");
            le.initCause(se);

            throw le;
        }

        if (debug) {
            System.out.println("[KeyStoreLoginModule] login: exit");
        }
        return true;
    }

    /**
     * Indicates the user is accepted. 
     * <p>
     * This method is called only if the user is authenticated by all modules in
     * the login configuration file. The principal objects will be added to the 
     * stored subject.
     * 
     * @return false if for some reason the principals cannot be added; true
     *         otherwise
     * 
     * @exception LoginException
     *                LoginException is thrown if the subject is readonly or if
     *                any unrecoverable exceptions is encountered.
     * 
     * @see LoginModule#commit()
     */
    public boolean commit() throws LoginException {
        if (debug) {
            System.out.println("[KeyStoreLoginModule] commit: entry");
        }

        if (principals.isEmpty()) {
            throw new IllegalStateException("Commit is called out of sequence");
        }

        if (subject.isReadOnly()) {
            throw new LoginException("Subject is Readonly");
        }

        subject.getPrincipals().addAll(principals);
        subject.getPublicCredentials().addAll(publicCreds);
        subject.getPrivateCredentials().addAll(privateCreds);

        principals.clear();
        publicCreds.clear();
        privateCreds.clear();

        if (debug) {
            System.out.println("[KeyStoreLoginModule] commit: exit");
        }
        return true;
    }

    /**
     * Indicates the user is not accepted
     * 
     * @see LoginModule#abort()
     */
    public boolean abort() throws LoginException {
        boolean b = logout();
        return b;
    }

    /**
     * Logs the user out. Clear all the maps.
     * 
     * @see LoginModule#logout()
     */
    public boolean logout() throws LoginException {


        // Clear the instance variables
        principals.clear();
        publicCreds.clear();
        privateCreds.clear();

        // clear maps in the subject
        if (!subject.isReadOnly()) {
            if (subject.getPrincipals() != null) {
                subject.getPrincipals().clear();
            }

            if (subject.getPublicCredentials() != null) {
                subject.getPublicCredentials().clear();
            }

            if (subject.getPrivateCredentials() != null) {
                subject.getPrivateCredentials().clear();
            }
        }
        return true;
    }

    /**
     * Validates the user name and password based on the keystore.
     * 
     * @param userName user name
     * @param password password
     * @throws SecurityException if any exceptions encountered
     */
    private void validate(String userName, char password[])
        throws SecurityException {

        PrivateKey privateKey = null;

        // Get the private key from the keystore
        try {
            privateKey = (PrivateKey) keyStore.getKey(userName, password);
        }
        catch (NoSuchAlgorithmException nsae) {
            SecurityException se = new SecurityException();
            se.initCause(nsae);
            throw se;
        }
        catch (KeyStoreException kse) {
            SecurityException se = new SecurityException();
            se.initCause(kse);
            throw se;
        }
        catch (UnrecoverableKeyException uke) {
            SecurityException se = new SecurityException();
            se.initCause(uke);
            throw se;
        }

        if (privateKey == null) {
            throw new SecurityException("Invalid name: " + userName); 
        }

        // Check the certificats
        Certificate certs[] = null;
        try {
            certs = keyStore.getCertificateChain(userName);
        }
        catch (KeyStoreException kse) {
            SecurityException se = new SecurityException();
            se.initCause(kse);
            throw se;
        }

        if (debug) {
            System.out.println("  Print out the certificates:");
            for (int i = 0; i < certs.length; i++) {
                System.out.println("  certificate " + i);
                System.out.println("    " + certs[i]);
            }
        }

        if (certs != null && certs.length > 0) {

            // If the first certificate is an X509Certificate
            if (certs[0] instanceof X509Certificate) {
                try {
                    // Get the first certificate which represents the user
                    X509Certificate certX509 = (X509Certificate) certs[0];

                    // Create a principal
                    X500Principal principal = new X500Principal(certX509
                            .getIssuerDN()
                            .getName());
                    principals.add(principal);

                    if (debug) {
                        System.out.println("  Principal added: " + principal);
                    }
                    // Create the certification path object and add it to the 
                    // public credential set
                    CertificateFactory factory = CertificateFactory
                        .getInstance("X.509");
                    java.security.cert.CertPath certPath = factory
                        .generateCertPath(Arrays.asList(certs));
                    publicCreds.add(certPath);

                    // Add the private credential to the private credential set
                    privateCreds.add(new X500PrivateCredential(certX509,
                            privateKey, userName));

                }
                catch (CertificateException ce) {
                    SecurityException se = new SecurityException();
                    se.initCause(ce);
                    throw se;
                }
            }
            else {
                // The first certificate is not an X509Certificate
                // We just add the certificate to the public credential set
                // and the private key to the private credential set.
                publicCreds.add(certs[0]);
                privateCreds.add(privateKey);
            }
        }
    }
}

Authenticator-Plug-in für LDAP verwenden

Die Standardimplementierung "com.ibm.websphere.objectgrid.security.plugins.builtins.LDAPAuthenticator" wird bereitgestellt, um die Benutzernamens- und Kennwortauthentifizierung bei einem LDAP-Server durchzuführen. Diese Implementierung verwendet das Anmeldemodul "LDAPLogin", um den Benutzer an einem LDAP-Server (Lightweight Directory Access Protocol) anzumelden. Das folgende Snippet veranschaulicht, wie die Methode "authenticate" implementiert wird:

/**
* @see com.ibm.ws.objectgrid.security.plugins.Authenticator#
* authenticate(LDAPLogin)
*/
public Subject authenticate(Credential credential) throws
InvalidCredentialException, ExpiredCredentialException {

    UserPasswordCredential cred = (UserPasswordCredential) credential;
    LoginContext lc = null;
    try {
        lc = new LoginContext("LDAPLogin",
            new UserPasswordCallbackHandlerImpl(cred.getUserName(),
            cred.getPassword().toCharArray()));

        lc.login();

        Subject subject = lc.getSubject();

        return subject;
    }
    catch (LoginException le) {
        throw new InvalidCredentialException(le);
    }
    catch (IllegalArgumentException ile) {
        throw new InvalidCredentialException(ile);
    }
}

Außerdem wird mit eXtreme Scale das Anmeldemodul "com.ibm.websphere.objectgrid.security.plugins.builtins.LDAPLoginModule" für diesen Zweck bereitgestellt. Sie müssen die folgenden beiden Optionen in der JAAS-Anmeldekonfigurationsdatei angeben:

Das Anmeldemodul "LDAPLoginModule" ruft die Methode com.ibm.websphere.objectgrid.security.plugins.builtins.LDAPAuthentcationHelper.authenticate auf. Das folgende Code-Snippet zeigt, wie Sie die Methode "authenticate" von LDAPAuthenticationHelper implementieren:

/**
* Benutzer über das LDAP-Verzeichnis authentifizieren.
* @param user the user ID, e.g., uid=xxxxxx,c=us,ou=bluepages,o=ibm.com
* @param pwd the password
*
* @throws NamingException
*/
public String[] authenticate(String user, String pwd)
throws NamingException {
    Hashtable env = new Hashtable();
    env.put(Context.INITIAL_CONTEXT_FACTORY, factoryClass);
    env.put(Context.PROVIDER_URL, providerURL);
    env.put(Context.SECURITY_PRINCIPAL, user);
    env.put(Context.SECURITY_CREDENTIALS, pwd);
    env.put(Context.SECURITY_AUTHENTICATION, "simple");

    InitialContext initialContext = new InitialContext(env);

    // Benutzer suchen.
    DirContext dirCtx = (DirContext) initialContext.lookup(user);

    String uid = null;
    int iComma = user.indexOf(",");
    int iEqual = user.indexOf("=");
    if (iComma > 0 && iComma > 0) {
        uid = user.substring(iEqual + 1, iComma);
    }
    else {
        uid = user;
    }

    Attributes attributes = dirCtx.getAttributes("");

    // UID prüfen.
    String thisUID = (String) (attributes.get(UID).get());

    String thisDept = (String) (attributes.get(HR_DEPT).get());

    if (thisUID.equals(uid)) {
        return new String[] { thisUID, thisDept };
    }
    else {
        	        return null;
    }
}

Wenn die Authentifizierung erfolgreich ist, werden ID und Kennwort als gültig eingestuft. Anschließend ruft das Anmeldemodul die ID-Informationen und Abteilungsinformationen über diese Methode "authenticate" ab. Das Anmeldemodul erstellt zwei Principals: SimpleUserPrincipal und SimpleDeptPrincipal. Sie können das authentifizierte Subject-Objekte für die Gruppenberechtigung (in diesem Fall ist die Abteilung eine Gruppe) und Berechtigung von Einzelpersonen verwenden.

Das folgende Beispiel zeigt eine Anmeldemodulkonfiguration, die für die Anmeldung beim LDAP-Server verwendet wird:

LDAPLogin { com.ibm.websphere.objectgrid.security.plugins.builtins.LDAPLoginModule required
    providerURL="ldap://directory.acme.com:389/"
    factoryClass="com.sun.jndi.ldap.LdapCtxFactory";
};

In der vorherigen Konfiguration zeigt der LDAP-Server auf ldap://directory.acme.com:389/server. Ändern Sie diese Einstellung in Ihren LDAP-Server. Dieses Anmeldemodul verwendet die bereitgestellte ID und das bereitgestellte Kennwort für die Verbindungsherstellung zum LDAP-Server. Diese Implementierung ist nur für Testzwecke bestimmt.

Authenticator-Plug-in für WebSphere Application Server verwenden

eXtreme Scale stellt auch die integrierte Implementierung "com.ibm.websphere.objectgrid.security.plugins.builtins.WSTokenAuthenticator" bereit, mit der Sie die Sicherheitsinfrastruktur von WebSphere Application Server verwenden können. Diese integrierte Implementierung kann verwendet werden, wenn die folgenden Bedingungen zutreffen:

  1. Die globale Sicherheit von WebSphere Application Server ist aktiviert.
  2. Alle eXtreme-Scale-Clients und -Server sind in JVMs von WebSphere Application Server gestartet.
  3. Diese Anwendungsserver befinden sich in derselben Sicherheitsdomäne.
  4. Der eXtreme-Scale-Client ist bereits in WebSphere Application Server authentifiziert.

Der Client kann die Klasse com.ibm.websphere.objectgrid.security.plugins.builtins.WSTokenCredentialGenerator verwenden, um einen Berechtigungsnachweis zu generieren. Der Server verwendet diese Authenticator-Implementierungsklasse, um den Berechtigungsnachweis zu authentifizieren. Bei erfolgreicher Authentifizierung des Tokens wird ein Subject-Objekt zurückgegeben.

In diesem Szenario wird die Tatsache genutzt, dass der Client bereits authentifiziert wurde. Da sich die Anwendungsserver, die Server haben, in derselben Sicherheitsdomäne wie die Anwendungsserver befinden, die Clients haben, können die Sicherheitstoken vom Client an den Server weitergegeben werden, so dass dieselbe Benutzerregistry nicht erneut authentifiziert werden muss.

Authenticator-Plug-in für Tivoli Access Manager verwenden

Tivoli Access Manager wird weithin als Sicherheitsserver eingesetzt. Sie können Authenticator auch über die mit Tivoli Access Manager bereitgestellten Anmeldemodule implementieren.

Zum Authentifizieren eines Benutzers für Tivoli Access Manager wenden Sie das Anmeldemodul "com.tivoli.mts.PDLoginModule" an, das erfordert, dass die aufrufende Anwendung die folgenden Informationen bereitstellt:

  1. einen Principal-Namen (als Kurznamen oder als X.500-Namen (DN)),
  2. ein Kennwort.

Das Anmeldemodul authentifiziert den Principal und gibt den Berechtigungsnachweis von Tivoli Access Manager zurück. Das Anmeldemodul erwartet, dass die aufrufende Anwendung die folgenden Informationen bereitstellt:

  1. den Benutzernamen in einem javax.security.auth.callback.NameCallback-Objekt,
  2. das Kennwort in einem javax.security.auth.callback.PasswordCallback-Objekt.

Nachdem der Berechtigungsnachweis von Tivoli Access Manager erfolgreich abgerufen wurde, erstellt das JAAS-Anmeldemodul ein Subject- und ein PDPrincipal-Objekt. Es wird keine integrierte Lösung für die Authentifizierung in Tivoli Access Manager bereitgestellt, weil die Authentifizierung nur über das Modul "PDLoginModule" erfolgt. Weitere Einzelheiten finden Sie in der Veröffentlichung "IBM® Tivoli Access Manager Authorization Java Classes Developer Reference".

Sichere Verbindung zu WebSphere eXtreme Scale herstellen

Um eine sichere Verbindung zwischen einem eXtreme-Scale-Client und einem Server herzustellen, können Sie jede beliebige connect-Methode in der Schnittstelle "ObjectGridManager" verwenden, die ein ClientSecurityConfiguration-Objekt akzeptiert. Im Folgenden sehen Sie ein kurzes Beispiel:

public ClientClusterContext connect(String catalogServerEndpoints, 
		 ClientSecurityConfiguration securityProps,
     URL overRideObjectGridXml) throws ConnectException;

Diese Methode akzeptiert einen Parameter des Typs "ClientSecurityConfiguration", der eine Schnittstelle ist, die eine Clientsicherheitskonfiguration darstellt. Sie können die allgemein zugängliche API "com.ibm.websphere.objectgrid.security.config.ClientSecurityConfigurationFactory" verwenden, um eine Instanz mit Standardwerten zu erstellen, oder Sie können eine Instanz erstellen, indem Sie die Eigenschaftendatei des eXtreme-Scale-Clients übergeben. Diese Datei enthält die folgenden Eigenschaften, die sich auf die Authentifizierung beziehen. Der mit einem Pluszeichen (+) markierte Wert ist der Standardwert.

  • securityEnabled (true, false+): Diese Eigenschaft zeigt an, ob die Sicherheit aktiviert ist. Wenn ein Client eine Verbindung zu einem Server herstellt, muss die Eigenschaft "securityEnabled" auf der Client- und auf der Serverseite denselben Wert haben: true oder false. Sollte die Sicherheit auf dem verbindungsherstellenden Server beispielsweise aktiviert sein, muss die Eigenschaft auch auf dem Client auf "true" gesetzt werden, damit die Verbindung zum Server hergestellt werden kann.
  • authenticationRetryCount (ganzzahliger Wert, 0+): Diese Eigenschaft bestimmt, wie oft die Anmeldung wiederholt wird, wenn ein Berechtigungsnachweis verfallen ist. Beim Wert 0 wird die Anmeldung nicht wiederholt. Die Authentifizierungswiederholung gilt nur für den Fall, dass der Berechtigungsnachweis verfallen ist. Wenn der Berechtigungsnachweis nicht gültig ist, findet keine Wiederholung statt. Ihre Anwendung ist für die Wiederholung der Operation verantwortlich.

Nachdem Sie ein com.ibm.websphere.objectgrid.security.config.ClientSecurityConfiguration-Objekt erstellt haben, definieren Sie das credentialGenerator-Objekt auf dem Client mit der folgenden Methode:

/**
* {@link CredentialGenerator}-Objekt für diesen Client definieren.
* @param generator Das CredentialGenerator-Objekt, das dem Client zugeordnet wird.
*/
void setCredentialGenerator(CredentialGenerator generator);
Sie können das CredentialGenerator-Objekt auch wie folgt in der Eigenschaftendatei des eXtreme-Scale-Clients setzen:
  • credentialGeneratorClass: Der Name der Implementierungsklasse für das CredentialGenerator-Objekt. Diese Klasse muss einen Standardkonstruktor haben.
  • credentialGeneratorProps: Die Eigenschaften für die Klasse "CredentialGenerator". Bei einem Wert ungleich null, wird diese Eigenschaft mit der Methode "setProperties(String)" auf das erstellte CredentialGenerator-Objekt gesetzt.

Es folgt ein Beispiel für die Instanziierung einer ClientSecurityConfiguration, die anschließend für die Verbindungsherstellung zum Server verwendet wird.

/**
* Gesicherten ClientClusterContext abrufen.
* @return Ein sicheres ClientClusterContext-Objekt.
*/
protected ClientClusterContext connect() throws ConnectException {
ClientSecurityConfiguration csConfig = ClientSecurityConfigurationFactory
.getClientSecurityConfiguration("/properties/security.ogclient.props");

UserPasswordCredentialGenerator gen= new
UserPasswordCredentialGenerator("manager", "manager1");

csConfig.setCredentialGenerator(gen);

return objectGridManager.connect(csConfig, null);
}

Wenn die connect-Methode aufgerufen wird, ruft der eXtreme-Scale-Client die Methode "CredentialGenerator.getCredential" auf, um den Clientberechtigungsnachweis abzurufen. Dieser Berechtigungsnachweis wird zusammen mit der Verbindungsanforderung zur Authentifizierung an den Server gesendet.

Für jede Sitzung eine andere CredentialGenerator-Instanz verwenden

In manchen Fällen stellt ein eXtreme-Scale-Client nur eine einzige Clientidentität dar. In anderen Fällen wiederum kann er mehrere Identitäten darstellen. Es folgt ein Szenario für den letzten Fall: Es wird ein eXtreme-Scale-Client erstellt und in einem Webserver gemeinsam genutzt. Alle Servlets in diesem Webserver verwenden diesen einen eXtreme-Scale-Client. Da jedes Servlet einen anderen Webclient darstellt, verwenden Sie unterschiedliche Berechtigungsnachweise, wenn Sie Anforderungen an eXtreme-Scale-Server senden.

WebSphere eXtreme Scale unterstützt die Änderung des Berechtigungsnachweises auf Sitzungsebene. Jede Sitzung kann ein anderes CredentialGenerator-Objekt verwenden. Deshalb können die zuvor beschriebenen Szenarien realisiert werden, indem Sie das Servlet eine Sitzung mit einem anderen CredentialGenerator-Objekt abrufen lassen. Das folgende Beispiel veranschaulicht die Methode "ObjectGrid.getSession(CredentialGenerator)" in der Schnittstelle "ObjectGridManager".

/**
     * Sitzung mit <code>CredentialGenerator</code> abrufen.
     * <p>
     * Diese Methode kann nur vom ObjectGrid-Client in einer Client/Server-Umgebung
     * aufgerufen werden. Wenn ObjectGrid in einem lokalen Modell verwendet wird, d. h.
     * in derselben JVM ohne vorhandenen Client oder Server, muss die Methode
     * <code>getSession(Subject)</code> oder das Plug-in <code>SubjectSource</code>
     * zum Sichern des ObjectGrids verwendet werden.
     *
     * <p>Wenn die Methode <code>initialize()</code> nicht vor dem ersten
     * Aufruf von <code>getSession</code> aufgerufen wird, findet eine
     * implizite Implementierung statt. Auf diese Weise wird sichergestellt, dass die
     * gesamte Konfiguration abgeschlossen ist, bevor sie zur Laufzeit benötigt wird.</p>
     *
     * @param credGen Ein <code>CredentialGenerator</code> für die Generierung
     *                eines Berechtigungsnachweises für die zurückgegebene Sitzung.
     *
     * @return Eine Instanz von <code>Session</code>.
     *
     * @throws ObjectGridException, wenn während der Verarbeitung ein Fehler auftritt.
          * @throws TransactionCallbackException, wenn <code>TransactionCallback</code>
     *         eine Ausnahme auslöst.
     * @throws IllegalStateException, wenn diese Methode nach dem Aufruf der
     *         Methode <code>destroy()</code> aufgerufen wird.
     *
     * @see #destroy()
     * @see #initialize()
     * @see CredentialGenerator
     * @see Session
     * @since WAS XD 6.0.1
 */
Session getSession(CredentialGenerator credGen) throws
ObjectGridException, TransactionCallbackException;

Beispiel:

ObjectGridManager ogManager = ObjectGridManagerFactory.getObjectGridManager();

CredentialGenerator credGenManager = new UserPasswordCredentialGenerator("manager", "xxxxxx");
CredentialGenerator credGenEmployee = new UserPasswordCredentialGenerator("employee", "xxxxxx");

ObjectGrid og = ogManager.getObjectGrid(ctx, "accounting");

// Sitzung mit CredentialGenerator abrufen
Session session = og.getSession(credGenManager );

// Mitarbeiterzuordnung abrufen
ObjectMap om = session.getMap("employee");

// Transaktion starten
session.begin();

Object rec1 = map.get("xxxxxx");

session.commit();

// Weitere Sitzung mit einem anderen CredentialGenerator abrufen
session = og.getSession(credGenEmployee );

// Mitarbeiterzuordnung abrufen
om = session.getMap("employee");

// Transaktion starten
session.begin();

Object rec2 = map.get("xxxxx");

session.commit();

Wenn Sie die Methode "ObjectGrid.getSession" verwenden, um ein Session-Objekt abzurufen, verwendet die Sitzung das CredentialGenerator-Objekt, das im ClientConfigurationSecurity-Objekt definiert ist. Die Methode "ObjectGrid.getSession(CredentialGenerator)" überschreibt den im ClientSecurityConfiguration-Objekt definierten CredentialGenerator.

Wenn Sie das Session-Objekt wiederverwenden können, findet eine Leistungssteigerung statt. Der Aufruf der Methode "ObjectGrid.getSession(CredentialGenerator)" ist jedoch nicht sehr kostenintensiv. Die Hauptkosten entstehen durch die längere Dauer der Objekt-Garbage-Collection. Stellen Sie sicher, dass die Referenzen nach der Arbeit mit den Session-Objekten freigegeben werden. Wenn Ihr Session-Objekt die Identität zur gemeinsamen Nutzung bereitstellen kann, können Sie im Allgemeinen versuchen, das Session-Objekt wiederzuverwenden. Wenn nicht, verwenden Sie die Methode "ObjectGrid.getSession(CredentialGenerator)".