Beispiel: Implementierung von com.ibm.wsspi.security.token.SingleSignonToken
Diese Datei enthält ein Beispiel für eine SSO-Implementierung. Der folgende Beispielcode erweitert keine abstrakte Klasse, sondern implementiert die Schnittstelle "com.ibm.wsspi.security.token.SingleSignonToken" direkt. Sie können die Schnittstelle direkt implementieren, aber dies kann dazu führen, dass Sie Code doppelt schreiben. Die direkte Implementierung der Schnittstelle empfiehlt sich jedoch, wenn die Methoden für die Bearbeitung der verschiedenen Tokenimplementierungen stark voneinander abweichen.
Informationen zum Implementieren eines angepassten SSO-Tokens finden Sie im Artikel Angepasstes SSO-Token für die Weitergabe von Sicherheitsattributen implementieren.
package com.ibm.websphere.security.token;
import com.ibm.websphere.security.WSSecurityException;
import com.ibm.websphere.security.auth.WSLoginFailedException;
import com.ibm.wsspi.security.token.*;
import com.ibm.websphere.security.WebSphereRuntimePermission;
import java.io.ByteArrayOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataOutputStream;
import java.io.DataInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.io.InputStream;
import java.util.ArrayList;
public class CustomSingleSignonTokenImpl implements com.ibm.wsspi.security.
token.SingleSignonToken
{
private java.util.Hashtable hashtable = new java.util.Hashtable();
private byte[] tokenBytes = null;
// 2 hours in millis, by default
private static long expire_period_in_millis = 2*60*60*1000;
/**
* Konstruktor für die Erstellung der ersten SingleSignonToken-Instanz
*/
public CustomSingleSignonTokenImpl (String principal)
{
// Principal im Token festlegen
addAttribute("principal", principal);
// Tokenversion setzen
addAttribute("version", "1");
// Verfallszeit für Token setzen
addAttribute("expiration", new Long(System.currentTimeMillis() +
expire_period_in_millis).toString());
}
/**
* Konstruktor für die Entserialisierung der während einer Anmeldung mit Weitergabe empfangenen Tokenbytes
*/
public CustomSingleSignonTokenImpl (byte[] token_bytes)
{
try
{
// Sie sollten zum Entschlüsseln der Cookie-Bytes einen Entschlüsselungsalgorithmus implementieren
hashtable = (java.util.Hashtable) some_decryption_algorithm (token_bytes);
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Validiert das Token einschließlich Verfallsdatum, Signatur usw.
* @return boolean
*/
public boolean isValid ()
{
long expiration = getExpiration();
// Wenn Sie das Verfallsdatum auf 0 setzen, verfällt das Token nicht
if (expiration != 0)
{
// Zurückkehren, wenn das Token immer noch gültig ist
long current_time = System.currentTimeMillis();
boolean valid = ((current_time < expiration) ? true : false);
System.out.println("isValid: returning " + valid);
return valid;
}
else
{
System.out.println("isValid: returning true by default");
return true;
}
}
/**
* Ruft das Verfallsdatum als long-Wert ab
* @return long
*/
public long getExpiration()
{
// Ruft das Verfallsdatum aus der Hash-Tabelle ab
String[] expiration = getAttributes("expiration");
if (expiration != null && expiration[0] != null)
{
// Verfallsdatum ist immer das erste Element (nur eines verwenden)
System.out.println("getExpiration: returning " + expiration[0]);
return new Long(expiration[0]).longValue();
}
System.out.println("getExpiration: returning 0");
return 0;
}
/**
* Kehrt zurück, wenn das Token downstream weitergeleitet werden soll
* @return boolean
*/
public boolean isForwardable()
{
// Sie können wählen, ob das Token weitergegeben wird. Manchmal bietet es sich an,
// es nur lokal zu verwenden.
return true;
}
/**
* Ruft den Principal ab, zu dem dieses Token gehört. Bei Berechtigungstoken muss
* die Principal-Zeichenfolge mit der Principal-Zeichenfolge im Authentifizierungstoken
* übereinstimmen, andernfalls wird die Nachricht zurückgewiesen.
* @return String
*/
public String getPrincipal()
{
// Beliebige Kombination von Attributen
String[] principal = getAttributes("principal");
if (principal != null && principal[0] != null)
{
return principal[0];
}
System.out.println("getExpiration: returning null");
return null;
}
/**
* Gibt basierend auf den Informationen des Providers eine eindeutige ID für
* das Token zurück. Diese ID wird für das Caching verwendet und kann zusammen
* mit anderen eindeutigen Token-IDs im selben Subject verwendet werden.
*
* Diese Methode muss einen Nullwert zurückgeben, wenn die Zugriffs-ID des
* Benutzers eindeutig sein soll. Dies ist ein typisches Szenario.
*
* @return String
*/
public String getUniqueID()
{
// Beliebige Kombination von Attributen
return getPrincipal();
}
/**
* Ruft die Bytes ab, die gesendet werden sollen. Die Informationen im Byte-Array ([])
* müssen ausreichen, um das Tokenobjekt im Zielserver wiederherstellen zu können.
* @return byte[]
*/
public byte[] getBytes ()
{
if (hashtable != null)
{
try
{
// Folgendermaßen vorgehen, wenn das Objekt während der Festschreibung der Anmeldung schreibgeschützt
// ist. Dies gewährleistet, dass keine neue Daten definiert werden.
if (isReadOnly() && tokenBytes == null)
tokenBytes = some_encryption_algorithm (hashtable);
// Die Tokenbytes können mit einem ähnlichen Entschlüsselungsalgorithmus entserialisiert werden.
return tokenBytes;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
System.out.println("getBytes: returning null");
return null;
}
/**
* Ruft den Namen des Token ab, der zum Identifizieren des Byte-Array in der Protokollnachricht verwendet wird.
* @return String
*/
public String getName()
{
return "myCookieName";
}
/**
* Ruft die Version des Token in Kurzform ab. Wird ebenfalls zum Identifizieren
* des Byte-Array in der Protokollnachricht verwendet.
* @return short
*/
public short getVersion()
{
String[] version = getAttributes("version");
if (version != null && version[0] != null)
return new Short(version[0]).shortValue();
System.out.println("getVersion: returning default of 1");
return 1;
}
/**
* Beim Aufruf wird das Token unumkehrbar schreibgeschützt. Die Implementierung
* muss sicherstellen, dass alle Setter-Methoden dies prüfen.
*/
public void setReadOnly()
{
addAttribute("readonly", "true");
}
/**
* Interner Aufruf, um zu prüfen, ob das Token schreibgeschützt ist.
*/
private boolean isReadOnly()
{
String[] readonly = getAttributes("readonly");
if (readonly != null && readonly[0] != null)
return new Boolean(readonly[0]).booleanValue();
System.out.println("isReadOnly: returning default of false");
return false;
}
/**
* Ruft den Attributwert baiserend auf dem benannten Wert ab.
* @param String key
* @return String[]
*/
public String[] getAttributes(String key)
{
ArrayList array = (ArrayList) hashtable.get(key);
if (array != null && array.size() > 0)
{
return (String[]) array.toArray(new String[0]);
}
return null;
}
/**
* Definiert das Name/Wert-Paar für das Attribut. Gibt die zuvor für den Schlüssel (key)
* gesetzten Werte bzw. null zurück.
* @param String key
* @param String value
* @returns String[];
*/
public String[] addAttribute(String key, String value)
{
// Aktuellen Wert für den Schlüssel abrufen
ArrayList array = (ArrayList) hashtable.get(key);
if (!isReadOnly())
{
// ArrayList in einen String[] kopieren, solange sie existiert
String[] old_array = null;
if (array != null && array.size() > 0)
old_array = (String[]) array.toArray(new String[0]);
// Neue ArrayList reservieren, wenn keine gefunden wird
if (array == null)
array = new ArrayList();
// String der aktuellen ArrayList hinzufügen
array.add(value);
// Aktuelle ArrayList der Hash-Tabelle hinzufügen
hashtable.put(key, array);
// Altes Array zurückgeben
return old_array;
}
return (String[]) array.toArray(new String[0]);
}
/**
* Liste aller Attributnamen im Token abrufen
* @return java.util.Enumeration
*/
public java.util.Enumeration getAttributeNames()
{
return hashtable.keys();
}
/**
* Gegebenenfalls Deep-Copy des Token zurückgeben
* @return Object
*/
public Object clone()
{
com.ibm.websphere.security.token.CustomSingleSignonImpl deep_clone =
new com.ibm.websphere.security.token.CustomSingleSignonTokenImpl();
java.util.Enumeration keys = getAttributeNames();
while (keys.hasMoreElements())
{
String key = (String) keys.nextElement();
String[] list = (String[]) getAttributes(key);
for (int i=0; i<list.length; i++)
deep_clone.addAttribute(key, list[i]);
}
return deep_clone;
}
}