001: package com.technoetic.xplanner.security;
002:
003: import java.io.IOException;
004: import java.io.ObjectInputStream;
005: import java.io.Serializable;
006: import java.util.HashMap;
007: import java.util.Arrays;
008: import javax.security.auth.Subject;
009: import javax.servlet.http.HttpServletRequest;
010:
011: import org.apache.log4j.Logger;
012:
013: import com.technoetic.xplanner.security.module.ConfigurationException;
014: import com.technoetic.xplanner.security.module.LoginModuleLoader;
015: import com.technoetic.xplanner.util.LogUtil;
016:
017: public class LoginContext implements Serializable {
018: protected static final Logger LOG = LogUtil.getLogger();
019:
020: private transient LoginModule[] loginModules;
021: private transient LoginModuleLoader moduleLoader;
022: private Subject subject;
023: private int loginModuleIndex;
024:
025: public LoginContext() {
026: moduleLoader = createModuleLoader();
027: }
028:
029: public LoginContext(LoginModuleLoader moduleLoader) {
030: this .moduleLoader = moduleLoader;
031: }
032:
033: public void authenticate(String userId, String password)
034: throws AuthenticationException {
035: HashMap errorMap = new HashMap();
036: LoginModule[] modules = getLoginModules();
037: LoginModule loginModule = null;
038: for (int i = 0; i < modules.length; i++) {
039: try {
040: loginModule = modules[i];
041: subject = loginModule.authenticate(userId, password);
042: loginModuleIndex = i;
043: LOG.debug("Authenticating successfully " + this );
044: return;
045: } catch (AuthenticationException aex) {
046: errorMap.put(loginModule.getName(), aex.getMessage());
047: }
048: }
049: loginModuleIndex = -1;
050: LOG.debug("Failure to authenticate " + this );
051: throw new AuthenticationException(errorMap);
052: }
053:
054: public LoginModule getLoginModule() throws ConfigurationException {
055: LoginModule[] modules = getLoginModules();
056: if (loginModuleIndex >= modules.length) {
057: throw new RuntimeException("index of used login module="
058: + loginModuleIndex + ", number of modules="
059: + modules.length);
060: }
061: return modules[loginModuleIndex];
062: }
063:
064: public Subject getSubject() {
065: return subject;
066: }
067:
068: public void logout(HttpServletRequest request)
069: throws AuthenticationException {
070: LoginModule[] modules = getLoginModules();
071: for (int i = 0; i < modules.length; i++) {
072: modules[i].logout(request);
073: }
074: }
075:
076: protected LoginModule[] getLoginModules()
077: throws ConfigurationException {
078: if (loginModules == null) {
079: loginModules = moduleLoader.loadLoginModules();
080: }
081: return loginModules;
082: }
083:
084: // DEBT: The deserialization creating new LoginModule should be cleaned up when we have a bean context per session/request...
085: private final void readObject(ObjectInputStream in)
086: throws IOException, ClassNotFoundException {
087: in.defaultReadObject();
088: moduleLoader = createModuleLoader();
089: loginModules = getLoginModules();
090: LOG.debug("Deserializing... " + this );
091: }
092:
093: protected LoginModuleLoader createModuleLoader() {
094: return new LoginModuleLoader();
095: }
096:
097: public String toString() {
098: return "LoginContext{"
099: + "subject="
100: + subject
101: + ", loginModuleIndex="
102: + loginModuleIndex
103: + ", loginModules ="
104: + (loginModules == null ? null : Arrays
105: .asList(loginModules)) + ", moduleLoader="
106: + moduleLoader + '}';
107: }
108: }
|