|
|
/*
* Program: SSODelegatorFactoryImpl.java
* Purpose: Implementation for SSODelegator factory
* @author Ray Lai (ray.lai@sun.com)
* @version 1.0
* Updated: April 19, 2005, 11:41 AM
* Copyright: (c) 2005 by Sun Microsystems/Ray Lai under Common Development and Distribution License
* Remarks: Full program and documentation will be available under developer.java.net
* For simplicity, logger class is removed.
* You need JDK 1.5 for HashMap
* =====================================================================================
*
*/
package com.csp.identity;
import java.util.HashMap;
import com.csp.identity.*;
public class SSODelegatorFactoryImpl implements com.csp.identity.SSODelegatorFactory {
protected HashMap<String, com.csp.identity.SSOContextImpl> servicesMap = new HashMap(); // store serviceName, context
protected HashMap<String, Object> SSOTokenMap = new HashMap(); // store serviceName, SSOToken
protected static com.csp.identity.SSODelegatorFactoryImpl singletonInstance = null;
protected String ssoToken;
/** Constructor - Creates a new instance of SSODelegatorFactoryImpl */
private SSODelegatorFactoryImpl() {
// load config file for all security authorized service providers in Context
initConfig();
createSSOToken();
}
/**
* Validate security token before creating, closing or reconnecting to remote
* service provider.
* You can implement your security token validation process as per local requirements.
* You may want to re-use Credential Tokenizer to encapsulate the security token.
*
* In this example, we'll always return true for demo purpose.
*/
private boolean validateSecurityToken(Object securityToken) {
// to be implemented
return true;
}
/**
* Create a SSO connection with the remote service provider
* Need to pass a security token and the target service name.
* The service locator will look up where the service name is.
* A\nd then invoke the remote object class/URI based on the
* protocol binding.
*
* @param Object security token (for example, you can re-use Credential Tokenizer)
* @param String service name for the remote service provider
*/
public void createSSOConnection(Object securityToken, String serviceName) throws com.csp.identity.SSODelegatorException {
if (validateSecurityToken(securityToken) == true) {
try {
// load Java object class (or URI) via serviceLocator
com.csp.identity.SSOContextImpl context = servicesMap.get(serviceName);
String className = context.serviceLocator(serviceName);
Class clazz = Class.forName(className);
com.csp.identity.SSOServiceProvider serviceProvider
= (com.csp.identity.SSOServiceProvider)clazz.newInstance();
// invoke remote security service provider
serviceProvider.createService(context);
// update status=CREATE
context.setStatus(context.REMOTE_SERVICE_CREATED);
// update servicesMap and context
context.setCompRef(serviceProvider);
servicesMap.remove(serviceName);
servicesMap.put(serviceName, context);
this.setSSOTokenMap(serviceName);
}
catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
throw new com.csp.identity.SSODelegatorException("Class not found");
}
catch (InstantiationException ie) {
ie.printStackTrace();
throw new com.csp.identity.SSODelegatorException("Instantiation exception");
}
catch (IllegalAccessException iae) {
iae.printStackTrace();
throw new com.csp.identity.SSODelegatorException("Illegal access exception");
}
}
else {
// update status=error
System.out.println("Invalid security token presented!");
throw new com.csp.identity.SSODelegatorException("Invalid securitiy token");
}
}
/**
* Close a SSO connection with the remote service provider
* Need to pass a security token and the target service name.
* The service locator will look up where the service name is.
* And then invoke the remote object class/URI based on the
* protocol binding.
*
* @param Object security token (for example, you can re-use Credential Tokenizer)
* @param String service name for the remote service provider
*/
public void closeSSOConnection(Object securityToken, String serviceName) throws com.csp.identity.SSODelegatorException {
// to be implemented
if (validateSecurityToken(securityToken) == true) {
System.out.println(serviceName + ": Security token is valid");
// load Java object class (or URI) via serviceLocator
com.csp.identity.SSOContextImpl context = servicesMap.get(serviceName);
com.csp.identity.SSOServiceProvider serviceProvider = context.getCompRef();
if (serviceProvider == null) {
throw new com.csp.identity.SSODelegatorException("SSO connection not made.");
}
// invoke remote security service provider
serviceProvider.closeService();
// update status=CLOSED
context.setStatus(context.REMOTE_SERVICE_CLOSED);
// update servicesMap and context
context.removeCompRef();
servicesMap.remove(serviceName);
servicesMap.put(serviceName, context);
this.removeSSOTokenMap(serviceName);
}
else {
// update status=error
System.out.println(serviceName + ": Invalid security token presented!");
throw new com.csp.identity.SSODelegatorException("Invalid securitiy token");
}
}
/**
* Load the configuration into the SSODelegatorFactory implementation so that
* it will know which are the remote service providers (including the
* logical service name and the object class/URI for service invocation.
*
* For demo purpose, we hard-coded a few examples here. We can also use
* Apache Commons Configuration to load a config.xml property file.
*/
private void initConfig() {
// load a list of "authorized" security service providers from the config file
// and load into an array of SSOContext
try {
// create sample data
com.csp.identity.SSOContextImpl context1 = new com.csp.identity.SSOContextImpl();
com.csp.identity.SSOContextImpl context2 = new com.csp.identity.SSOContextImpl();
context1.setServiceName("service1");
context1.setProtocolBinding("SOAP");
context2.setServiceName("service2");
context2.setProtocolBinding("RMI");
this.servicesMap.put("service1", context1);
this.servicesMap.put("service2", context2);
}
catch (com.csp.identity.SSODelegatorException se) {
se.printStackTrace();
}
}
/**
*
* You need to pass a security token before you can get the SSODelegator instance.
* Rationale:
* 1. This ensures that only authenticated/authorized subjects can invoke the SSO Delegator.
* (authentication and authorization requirements).
* 2. No one can invoke the constructor directly (visibility and segregation requirements).
* 3. Besides, there is only a singleton copy (singleton requirement).
*
* @param Object security token
*/
public static com.csp.identity.SSODelegatorFactoryImpl getSSODelegator(Object securityToken) {
synchronized (com.csp.identity.SSODelegatorFactoryImpl.class) {
if (singletonInstance==null) {
singletonInstance = new com.csp.identity.SSODelegatorFactoryImpl();
}
return singletonInstance;
}
}
/**
* This private method creates a SSO token to resemble a SSO session has been
* created to connect to remote security service providers.
* In practice, this security token should be implemented in any object type
* based on local requirements. You can also re-use the SecurityToken object
* type from the Credential Tokenizer.
*
* For demo purpose, we'll use a string. You can also use the String format
* to represent a base64 encoded format of a SSO token.
*/
private void createSSOToken() {
// to be implemented
this.ssoToken = "myPrivateSSOToken";
}
/**
* Register a SSOToken in the HashMap that a remote service provider
* connection has been made.
*
* @param String serviceName
*/
private void setSSOTokenMap(String serviceName) {
this.SSOTokenMap.put(serviceName, this.ssoToken);
}
/**
* Get a SSOToken in the HashMap that a remote service provider
* connection has been made.
*
* @param String serviceName
* @return Object SSOToken (in this demo, we'll use a String object)
*/
private Object getSSOTokenMap(String serviceName) {
return (String)this.SSOTokenMap.get(serviceName);
}
/**
* Remove a SSOToken from the HashMap that a remote service provider
* connection has been made.
*
* @param String serviceName
*/
private void removeSSOTokenMap(String serviceName) {
this.SSOTokenMap.remove(serviceName);
}
/**
* Get status from the remote service provicer.
* Need to pass a security token and the target service name.
* The service locator will look up where the service name is.
* And then invoke the remote object class/URI based on the
* protocol binding.
*
* @param Object security token (for example, you can re-use Credential Tokenizer)
* @param String service name for the remote service provider
*/
public String getServiceStatus(Object securityToken, String serviceName) throws com.csp.identity.SSODelegatorException {
if (validateSecurityToken(securityToken) == true) {
System.out.println(serviceName + ": Security token is valid");
// load Java object class (or URI) via serviceLocator
com.csp.identity.SSOContextImpl context = servicesMap.get(serviceName);
return context.getStatus();
}
else {
// update status=error
System.out.println(serviceName + ": Invalid security token presented!");
throw new com.csp.identity.SSODelegatorException("Invalid securitiy token");
}
}
}
|