Example: com.ibm.wsspi.security.token.PropagationToken implementation
Use this file to see an example of a PropagationToken implementation. The following sample code does not extend an abstract class, but rather implements the com.ibm.wsspi.security.token.PropagationToken interface directly. You can implement the interface directly, but it might cause you to write duplicate code. However, you might choose to implement the interface directly if there are considerable differences between how you handle the various token implementations.
For information on how to implement a custom PropagationToken, see Implementing a custom PropagationToken.
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 CustomPropagationTokenImpl implements com.ibm.wsspi.security. token.PropagationToken { 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; private long counter = 0; /** * The constructor that is used to create initial PropagationToken instance */ public CustomAbstractTokenImpl () { // set the token version addAttribute("version", "1"); // set the token expiration addAttribute("expiration", new Long(System.currentTimeMillis() + expire_period_in_millis).toString()); } /** * The constructor that is used to deserialize the token bytes received * during a propagation login. */ public CustomAbstractTokenImpl (byte[] token_bytes) { try { hashtable = (java.util.Hashtable) com.ibm.wsspi.security.token. WSOpaqueTokenHelper.deserialize(token_bytes); } catch (Exception e) { e.printStackTrace(); } } /** * Validates the token including expiration, signature, and so on. * @return boolean */ public boolean isValid () { long expiration = getExpiration(); // if you set the expiration to 0, it does not expire if (expiration != 0) { // return if this token is still valid 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; } } /** * Gets the expiration as a long type. * @return long */ public long getExpiration() { // get the expiration value from the hashtable String[] expiration = getAttributes("expiration"); if (expiration != null && expiration[0] != null) { // expiration is the first element (should only be one) System.out.println("getExpiration: returning " + expiration[0]); return new Long(expiration[0]).longValue(); } System.out.println("getExpiration: returning 0"); return 0; } /** * Returns if this token should be forwarded/propagated downstream. * @return boolean */ public boolean isForwardable() { // We can choose whether your token gets propagated. In some cases // you might want the token to be local only. return true; } /** * Gets the principal that this token belongs to. If this token is an * authorization token, this principal string must match the authentication * token principal string or the message is rejected. * @return String */ public String getPrincipal() { // It is not necessary for the PropagtionToken to return a principal, // because it is not user-centric. return ""; } /** * Returns the unique identifier of the token based upon information that * the provider considers makes it a unique token. This identifier is used * for caching purposes and might be used in combination with other token * unique IDs that are part of the same Subject. * * This method should return null if you want the accessID of the user to * represent its uniqueness. This is the typical scenario. * * @return String */ public String getUniqueID() { // If you want to propagate the changes to this token, change the // value that this unique ID returns whenever the token is changed. // Otherwise, CSIv2 uses an existing session when everything else is // the same. This getUniqueID ischecked by CSIv2 to determine the // session lookup. return counter; } /** * Gets the bytes to be sent across the wire. The information in the byte[] * needs to be enough to recreate the Token object at the target server. * @return byte[] */ public byte[] getBytes () { if (hashtable != null) { try { // Do this if the object is set to read-only during login commit // because this guarantees that no new data is set. if (isReadOnly() && tokenBytes == null) tokenBytes = com.ibm.wsspi.security.token.WSOpaqueTokenHelper. serialize(hashtable); // We can deserialize this in the downstream login module using // WSOpaqueTokenHelper.deserialize() return tokenBytes; } catch (Exception e) { e.printStackTrace(); return null; } } System.out.println("getBytes: returning null"); return null; } /** * Gets the name of the token, which is used to identify the byte[] in the * protocol message. * @return String */ public String getName() { return this.getClass().getName(); } /** * Gets the version of the token as an short type. This code also is used * to identify the byte[] in the protocol message. * @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; } /** * When called, the token becomes irreversibly read-only. The implementation * needs to ensure that any setter methods check that this read-only flag has * been set. */ public void setReadOnly() { addAttribute("readonly", "true"); } /** * Called internally to see if the token is readonly */ 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; } /** * Gets the attribute value based on the named value. * @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; } /** * Sets the attribute name and value pair. Returns the previous values set * for the key, or returns null if the value is not previously set. * @param String key * @param String value * @returns String[]; */ public String[] addAttribute(String key, String value) { // Gets the current value for the key ArrayList array = (ArrayList) hashtable.get(key); if (!isReadOnly()) { // Increments the counter to change the uniqueID counter++; // Copies the ArrayList to a String[] as it currently exists String[] old_array = null; if (array != null && array.size() > 0) old_array = (String[]) array.toArray(new String[0]); // Allocates a new ArrayList if one was not found if (array == null) array = new ArrayList(); // Adds the String to the current array list array.add(value); // Adds the current ArrayList to the Hashtable hashtable.put(key, array); // Returns the old array return old_array; } return (String[]) array.toArray(new String[0]); } /** * Gets the list of all of the attribute names present in the token. * @return java.util.Enumeration */ public java.util.Enumeration getAttributeNames() { return hashtable.keys(); } /** * Returns a deep clone of this token. This is typically used by the session * logic of the CSIv2 server to create a copy of the token as it exists in the * session. * @return Object */ public Object clone() { com.ibm.websphere.security.token.CustomPropagationTokenImpl deep_clone = new com.ibm.websphere.security.token.CustomPropagationTokenImpl(); 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; } }