Exemple : Implémentation com.ibm.wsspi.security.token.SingleSignonToken
Ce fichier permet d'obtenir un exemple d'implémentation de connexion unique. L'exemple de code suivant n'étend pas de classe abstraite. Il implémente l'interface com.ibm.wsspi.security.token.SingleSignonToken directement. Vous pouvez implémenter l'interface directement, mais cela peut vous amener à écrire du code en double. Vous pouvez toutefois décider d'implémenter l'interface directement s'il existe d'importantes différences entre la façon dont vous gérez les diverses implémentations de jeton.
Pour plus d'informations sur l'implémentation d'un jeton de connexion unique personnalisé, voir Implémentation d'un jeton de connexion unique personnalisé pour la propagation des attributs de sécurité.
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;
// par défaut 2 heures, en millisecondes
private static long délai_expiration_en_millisecondes = 2*60*60*1000;
/**
* Constructeur utilisé pour créer une instance SingleSignonToken initiale
*/
public CustomSingleSignonTokenImpl (String principal)
{
// définit le principal dans le jeton
addAttribute("principal", principal);
// définit la version du jeton
addAttribute("version", "1");
// définit le délai d'expiration du jeton
addAttribute("expiration", new Long(System.currentTimeMillis() +
délai_expiration_en_millisecondes).toString());
}
/**
* Constructeur utilisé pour désérialiser les octets de jeton reçus pendant une connexion par propagation.
*/
public CustomSingleSignonTokenImpl (byte[] token_bytes)
{
try
{
// Vous devez implémenter un algorithme de déchiffrement pour déchiffrer les octets du cookie
hashtable = (java.util.Hashtable) algorithme_de_chiffrement (octets_jeton);
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Valide le jeton y compris le délai d'expiration, la signature, etc.
* @return booléen
*/
public boolean isValid ()
{
long expiration = getExpiration();
// si l'expiration est définie sur 0, le jeton n'expire pas
if (expiration != 0)
{
// détermine si ce jeton est encore valide
long durée_actuelle = System.currentTimeMillis();
boolean valid = ((durée_actuelle < expiration) ? true : false);
System.out.println("isValid: returning " + valid);
return valid;
}
else
{
System.out.println("isValid : renvoie true par défaut");
return true;
}
}
/**
* Extrait l'expiration en tant que type long.
* @return long
*/
public long getExpiration()
{
// extrait la valeur de l'expiration dans la table de hachage
String[] expiration = getAttributes("expiration");
if (expiration != null && expiration[0] != null)
{
// L'expiration est toujours le premier élément et il ne doit y en avoir qu'une
System.out.println("getExpiration: returning " + expiration[0]);
return new Long(expiration[0]).longValue();
}
System.out.println("getExpiration: returning 0");
return 0;
}
/**
* Indique si ce jeton doit être transmis/propagé en aval.
* @return booléen
*/
public boolean isForwardable()
{
// Vous pouvez décider de faire propager vos jetons ou non. Dans certains cas,
// il peut être préférable qu'il soit local uniquement.
return true;
}
/**
* Extrait le principal auquel le jeton appartient. S'il s'agit d'un jeton d'autorisation,
* cette chaîne de principal doit correspondre à la chaîne de principal du jeton d'authentification ;
* si elle ne correspond pas, le message sera rejeté.
* @return chaîne
*/
public String getPrincipal()
{
// il peut s'agir de toute combinaison d'attributs
String[] principal = getAttributes("principal");
if (principal != null && principal[0] != null)
{
return principal[0];
}
System.out.println("getExpiration: returning null");
return null;
}
/**
* Renvoie un identificateur unique du jeton d'après les informations qui, selon le fournisseur,
* en font un jeton unique. Il est utilisé pour la mise en cache
* et peut être utilisé en association avec d'autres ID uniques de jeton faisant partie
* du même sujet.
*
* Cette méthode doit renvoyer la valeur null si vous souhaitez que l'ID accès de l'utilisateur représente
* l'unicité. Il s'agit du scénario type.
*
* @return chaîne
*/
public String getUniqueID()
{
// il peut s'agir de toute combinaison d'attributs
return getPrincipal();
}
/**
* Extrait les octets à envoyer via le réseau. Les informations contenues dans byte[]
* doivent être suffisantes pour recréer l'objet du jeton au niveau du serveur cible.
* @return byte[]
*/
public byte[] getBytes ()
{
if (hashtable != null)
{
try
{
// Faites ceci si l'objet est défini en lecture seule pendant la validation de la connexion ;
// cela garantit qu'aucune nouvelle donnée ne sera définie.
if (isReadOnly() && tokenBytes == null)
tokenBytes = algorithme_de_chiffrement (hashtable);
// Vous pouvez désérialiser les tokenBytes à l'aide d'un algorithme de chiffrement similaire.
return tokenBytes;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
System.out.println("getBytes : renvoie null");
return null;
}
/**
* Extrait le nom du jeton, utilisé pour identifier le byte[] dans le message de protocole.
* @return chaîne
*/
public String getName()
{
return "monNomDeCookie";
}
/**
* Extrait la version du jeton en tant que type court. Celle-ci permet également d'identifier
* le byte[] dans le message de protocole.
* @return court (short)
*/
public short getVersion()
{
String[] version = getAttributes("version");
if (version != null && version[0] != null)
return new Short(version[0]).shortValue();
System.out.println("getVersion : renvoie 1 par défaut");
return 1;
}
/**
* Lorsqu'il est appelé, le jeton devient irréversiblement en lecture seule. L'implémentation
* doit s'assurer que toutes les méthodes setter vérifient que ceci a été défini.
*/
public void setReadOnly()
{
addAttribute("readonly", "true");
}
/**
* Appelé en interne pour voir si le jeton est en lecture seule
*/
private boolean isReadOnly()
{
String[] readonly = getAttributes("readonly");
if (readonly != null && readonly[0] != null)
return new Boolean(readonly[0]).booleanValue();
System.out.println("isReadOnly : renvoie valeur par défaut false");
return false;
}
/**
* Extrait la valeur de l'attribut d'après la valeur nommée.
* @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;
}
/**
* Définit la paire nom d'attribut/valeur. Renvoie les valeurs précédentes définies pour la clé,
* ou null si elles n'ont pas été définies auparavant.
* @param String key
* @param String value
* @returns String[];
*/
public String[] addAttribute(String key, String value)
{
// Extrait la valeur courante de la clé
ArrayList array = (ArrayList) hashtable.get(key);
if (!isReadOnly())
{
// copie la liste de tableaux dans une String[] telle qu'elle existe actuellement
String[] old_array = null;
if (array != null && array.size() > 0)
old_array = (String[]) array.toArray(new String[0]);
// attribue une nouvelle liste de tableaux si aucune n'a été trouvée
if (array == null)
array = new ArrayList();
// ajoute la chaîne à la liste de tableaux en cours
array.add(value);
// ajoute la liste de tableaux en cours à la table de hachage
hashtable.put(key, array);
// renvoie l'ancien tableau
return old_array;
}
return (String[]) array.toArray(new String[0]);
}
/**
* Extrait la liste de tous les noms d'attributs présents dans le jeton.
* @return java.util.Enumeration
*/
public java.util.Enumeration getAttributeNames()
{
return hashtable.keys();
}
/**
* Renvoie une copie en profondeur de ce jeton, si nécessaire.
* @return un objet
*/
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;
}
}