Ejemplo: implementación de com.ibm.wsspi.security.token.AuthenticationToken
En el ejemplo siguiente se ilustra una implementación de señal de autenticación. El código de ejemplo siguiente no amplía una clase abstracta sino que implementa directamente la interfaz com.ibm.wsspi.security.token.AuthenticationToken. Puede implementar directamente la interfaz pero es posible que tenga que escribir dos veces el código. No obstante, puede optar por implementar directamente la interfaz si hay alguna diferencia importante en el modo en que maneja las diferentes implementaciones de las señales.
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 CustomAuthenticationTokenImpl implements com.ibm.wsspi.security.
token.AuthenticationToken
{
private java.util.Hashtable hashtable = new java.util.Hashtable();
private byte[] tokenBytes = null;
// 2 horas en miliseg., de forma predeterminada
private static long expire_period_in_millis = 2*60*60*1000;
private String oidName = "su_nombre_oid";
// Realmente esta serie puede ser cualquier cosa si no desea utilizar un OID.
/**
* Constructor utilizado para crear una instancia de AuthenticationToken inicial
*/
public CustomAuthenticationTokenImpl (String principal)
{
// Establece el principal en la señal
addAttribute("principal", principal);
// Establece la versión de la señal
addAttribute("version", "1");
// Establece la caducidad de la señal
addAttribute("expiration", new Long(System.currentTimeMillis()
+ expire_period_in_millis).toString());
}
/**
* Constructor utilizado para deserializar los bytes de la señal recibidos durante una
* conexión de propagación.
*/
public CustomAuthenticationTokenImpl (byte[] token_bytes)
{
try
{
// Los datos de token_bytes deben estar firmados y cifrados si la tabla
// de totales de control actúa como un señal de autenticación.
hashtable = (java.util.Hashtable) custom_decryption_algorithm (token_bytes);
}
catch (Exception e)
{
e.printStackTrace();
}
}
/**
* Valida la señal incluidos la caducidad, la firma, etc.
* @return boolean
*/
public boolean isValid ()
{
long expiration = getExpiration();
// Si establece la caducidad en 0, la señal no caduca
if (expiration != 0)
{
// Devuelve una respuesta que identifica si la señal continúa siendo válida
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;
}
}
/**
* Obtiene la caducidad como un tipo long.
* @return long
*/
public long getExpiration()
{
// Obtiene el valor de caducidad de la tabla de totales de control
String[] expiration = getAttributes("expiration");
if (expiration != null && expiration[0] != null)
{
// La caducidad es el primer elemento y solo debe haber una caducidad
System.out.println("getExpiration: returning " + expiration[0]);
return new Long(expiration[0]).longValue();
}
System.out.println("getExpiration: returning 0");
return 0;
}
/**
* Indica si esta señal debe reenviarse o propagarse en sentido descendente.
* @return boolean
*/
public boolean isForwardable()
{
// Puede seleccionar si la señal se ha de propagar. En algunos casos,
// es posible que desee que esta operación se ejecute sólo localmente.
return true;
}
/**
* Obtiene el principal al que pertenece esta señal. Si este es una
* señal de autorización, esta serie de principal debe coincidir con
* la serie de principal de la señal de autenticación o se rechazará el mensaje.
* @return String
*/
public String getPrincipal()
{
// Este valor puede ser cualquier combinación de los atributos
String[] principal = getAttributes("principal");
if (principal != null && principal[0] != null)
{
return principal[0];
}
System.out.println("getExpiration: returning null");
return null;
}
/**
* Devuelve un identificador exclusivo de la señal basándose en la información que
* convierte esta señal en exclusiva según el proveedor. Este identificador se utiliza para * almacenamiento en memoria caché
* y se puede utilizar junto con otros ID exclusivos de señal que formen parte del
* mismo asunto.
*
* Este método debe devolver un valor nulo si desea que el accessID del usuario sea
* exclusivo. Este es el escenario típico.
*
* @return String
*/
public String getUniqueID()
{
// Si no desea que la búsqueda en la memoria caché se vea afectada, devuelva NULL aquí.
return null;
String cacheKeyForThisToken = "dynamic attributes";
// Si desea que la búsqueda en la memoria caché se vea afectada, devuelva una serie
// de atributos que serán factores para la búsqueda.
return cacheKeyForThisToken;
}
/**
* Obtiene los bytes que se enviarán a través de las comunicaciones. byte[] debe incluir la
* información necesaria para volver a crear el objeto de señal en el servidor de destino.
* @return byte[]
*/
public byte[] getBytes ()
{
if (hashtable != null)
{
try
{
// Haga lo siguiente si el objeto es de sólo lectura durante la confirmación de
// conexión ya que de este modo se asegura de que no se establezcan datos nuevos.
if (isReadOnly() && tokenBytes == null)
tokenBytes = custom_encryption_algorithm (hashtable);
return tokenBytes;
}
catch (Exception e)
{
e.printStackTrace();
return null;
}
}
System.out.println("getBytes: returning null");
return null;
}
/**
* Obtiene el nombre de la señal, que se utiliza para identificar byte[] en el
* mensaje de protocolo.
* @return String
*/
public String getName()
{
return oidName;
}
/**
* Obtiene la versión de la señal como un tipo short. También se utiliza
* para identificar byte[] en el mensaje de protocolo.
* @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;
}
/**
* Cuando se llama, la señal pasa a ser de sólo lectura de forma irreversible. La
* implementación ha de asegurarse de que los métodos set comprueben que se ha establecido este * estado.
*/
public void setReadOnly()
{
addAttribute("readonly", "true");
}
/**
* Se llama internamente para ver si la señal es de sólo lectura
*/
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;
}
/**
* Obtiene el valor del atributo basándose en el valor nombrado.
* @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;
}
/**
* Obtiene el par nombre-valor del atributo. Devuelve los valores de key ya establecidos
* o null si no se habían establecido anteriormente.
* @param String key
* @param String value
* @returns String[];
*/
public String[] addAttribute(String key, String value)
{
// Obtiene el valor actual para key
ArrayList array = (ArrayList) hashtable.get(key);
if (!isReadOnly())
{
// Copia ArrayList en String[] como existe actualmente
String[] old_array = null;
if (array != null && array.size() > 0)
old_array = (String[]) array.toArray(new String[0]);
// Asigna una ArrayList nueva si no se ha encontrado una
if (array == null)
array = new ArrayList();
// Añade la serie a la lista de matrices actual
array.add(value);
// Añade la ArrayList actual a la tabla de totales de control
hashtable.put(key, array);
// Devuelve la matriz antigua
return old_array;
}
return (String[]) array.toArray(new String[0]);
}
/**
* Obtiene la lista de todos los nombres de atributos existentes en la señal.
* @return java.util.Enumeration
*/
public java.util.Enumeration getAttributeNames()
{
return hashtable.keys();
}
/**
* Devuelve una copia exacta de esta señal, si es necesario.
* @return Object
*/
public Object clone()
{
com.ibm.wsspi.security.token.AuthenticationToken deep_clone =
new com.ibm.websphere.security.token.CustomAuthenticationTokenImpl();
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;
}
/**
* Este método devuelve true si esta señal almacena un ID de usuario y una contraseña
* en lugar de una señal.
* @return boolean
*/
public boolean isBasicAuth()
{
return false;
}
}