このファイルを使用して、シングル・サイン・オン・インプリメンテーションの例を示します。 以下のサンプル・コードは抽象クラスを拡張しませんが、 com.ibm.wsspi.security.token.SingleSignonToken インターフェースを直接インプリメントします。 この インターフェースは直接インプリメントすることが可能ですが、重複するコードが書き込まれる可能性があります。 ただし、各種のトークン・インプリメンテーションによって処理方法が大きく異なる 場合は、インターフェースを直接インプリメントするとよいでしょう。
カスタムのシングル・サインオン・トークンの実装方法について詳しくは、カスタム・シングル・サインオン・トークンのインプリメント を参照してください。
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; /** * Constructor used to create initial SingleSignonToken instance */ public CustomSingleSignonTokenImpl (String principal) { // set the principal in the token addAttribute("principal", principal); // set the token version addAttribute("version", "1"); // set the token expiration addAttribute("expiration", new Long(System.currentTimeMillis() + expire_period_in_millis).toString()); } /** * Constructor used to deserialize the token bytes received during a propagation login. */ public CustomSingleSignonTokenImpl (byte[] token_bytes) { try { // you should implement a decryption algorithm to decrypt the cookie bytes hashtable = (java.util.Hashtable) some_decryption_algorithm (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. * @return long */ public long getExpiration() { // get the expiration value from the hashtable String[] expiration = getAttributes("expiration"); if (expiration != null && expiration[0] != null) { // expiration will always be 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() { // You can choose whether your token gets propagated or not, in some cases // you might want it to be local only. return true; } /** * Gets the principal that this Token belongs to. If this is an authorization token, * this principal string must match the authentication token principal string or the * message will be rejected. * @return String */ public String getPrincipal() { // this could be any combination of attributes String[] principal = getAttributes("principal"); if (principal != null && principal[0] != null) { return principal[0]; } System.out.println("getExpiration: returning null"); return null; } /** * Returns a unique identifier of the token based upon information the provider * considers makes this a unique token. This will be used for caching purposes * and may 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 access ID of the user to represent * uniqueness. This is the typical scenario. * * @return String */ public String getUniqueID() { // this could be any combination of attributes return getPrincipal(); } /** * 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 read-only during login commit, // since this guarantees no new data gets set. if (isReadOnly() && tokenBytes == null) tokenBytes = some_encryption_algorithm (hashtable); // you can deserialize the tokenBytes using a similiar decryption algorithm. return tokenBytes; } catch (Exception e) { e.printStackTrace(); return null; } } System.out.println("getBytes: returning null"); return null; } /** * Gets the name of the token, used to identify the byte[] in the protocol message. * @return String */ public String getName() { return "myCookieName"; } /** * Gets the version of the token as a short. This is also 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 any setter methods check that this 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/value pair. Returns the previous values set for key, * or null if not previously set. * @param String key * @param String value * @returns String[]; */ public String[] addAttribute(String key, String value) { // get the current value for the key ArrayList array = (ArrayList) hashtable.get(key); if (!isReadOnly()) { // copy 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]); // allocate a new ArrayList if one was not found if (array == null) array = new ArrayList(); // add the String to the current array list array.add(value); // add the current ArrayList to the Hashtable hashtable.put(key, array); // return the old array return old_array; } return (String[]) array.toArray(new String[0]); } /** * Gets the List of all attribute names present in the token. * @return java.util.Enumeration */ public java.util.Enumeration getAttributeNames() { return hashtable.keys(); } /** * Returns a deep copying of this token, if necessary. * @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; } }