예제: com.ibm.wsspi.security.token.PropagationToken 구현
이 파일을 사용하여 전파 토큰 구현에 대한 예제를 볼 수 있습니다. 다음 샘플 코드는 추상 클래스를 확장하지 않고 com.ibm.wsspi.security.token.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()
{
// You 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 PropagationToken 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 is checked 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);
// You 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 a 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;
}
}