You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by lh...@apache.org on 2009/07/22 03:11:54 UTC

svn commit: r796597 - in /incubator/shiro/trunk: core/src/main/java/org/apache/shiro/mgt/ core/src/main/java/org/apache/shiro/subject/ core/src/test/java/org/apache/shiro/session/mgt/ web/src/main/java/org/apache/shiro/web/ web/src/main/java/org/apache...

Author: lhazlewood
Date: Wed Jul 22 01:11:54 2009
New Revision: 796597

URL: http://svn.apache.org/viewvc?rev=796597&view=rev
Log:
SHIRO-30 - enabled SecurityManager#getSubject(Map initData) method and altered underlying implementations to support this construct.  This allowed for a significant amount of duplicate boilerplate code to be consolidated into the DefaultSubjectFactory implementation

Modified:
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectFactory.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DefaultSessionManagerTest.java
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DelegatingSessionTest.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSubjectFactory.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DelegatingWebSessionManager.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DelegatingWebSecurityManagerTest.java

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java Wed Jul 22 01:11:54 2009
@@ -18,18 +18,7 @@
  */
 package org.apache.shiro.mgt;
 
-import java.io.Serializable;
-import java.net.InetAddress;
-import java.util.Collection;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.Authenticator;
-import org.apache.shiro.authc.LogoutAware;
+import org.apache.shiro.authc.*;
 import org.apache.shiro.authz.AuthorizationException;
 import org.apache.shiro.authz.Authorizer;
 import org.apache.shiro.crypto.Cipher;
@@ -40,6 +29,13 @@
 import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.Subject;
 import org.apache.shiro.util.ThreadContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
 
 
 /**
@@ -48,7 +44,7 @@
  * authentication, authorization, and session operations to wrapped {@link Authenticator}, {@link Authorizer}, and
  * {@link org.apache.shiro.session.mgt.SessionManager SessionManager} instances respectively via superclass
  * implementation.</p>
- *
+ * <p/>
  * <p>To greatly reduce and simplify configuration, this implementation (and its superclasses) will
  * create suitable defaults for all of its required dependencies, <em>except</em> the required one or more
  * {@link Realm Realm}s.  Because <code>Realm</code> implementations usually interact with an application's data model,
@@ -56,23 +52,22 @@
  * <tt>Realm</tt> implementation that 'knows' about your application's data/security model
  * (via {@link #setRealm} or one of the overloaded constructors).  All other attributes in this class hierarchy
  * will have suitable defaults for most enterprise applications.</p>
- *
+ * <p/>
  * <p><b>RememberMe notice</b>: This class supports the ability to configure a
  * {@link #setRememberMeManager RememberMeManager}
  * for <tt>RememberMe</tt> identity services for login/logout, BUT, a default instance <em>will not</em> be created
  * for this attribute at startup.
- *
+ * <p/>
  * <p>Because RememberMe services are inherently client tier-specific and
  * therefore aplication-dependent, if you want <tt>RememberMe</tt> services enabled, you will have to specify an
  * instance yourself via the {@link #setRememberMeManager(RememberMeManager) setRememberMeManager}
  * mutator.  However if you're reading this JavaDoc with the
  * expectation of operating in a Web environment, take a look at the
- * {@link org.apache.shiro.web.DefaultWebSecurityManager DefaultWebSecurityManager} implementation, which
+ * {@code org.apache.shiro.web.DefaultWebSecurityManager} implementation, which
  * <em>does</em> support <tt>RememberMe</tt> services by default at startup.
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
- * @see org.apache.shiro.web.DefaultWebSecurityManager
  * @since 0.2
  */
 public class DefaultSecurityManager extends SessionsSecurityManager {
@@ -197,13 +192,22 @@
         return ThreadContext.getSessionId();
     }
 
-    protected Subject createSubject() {
-        Subject subject = null;
+    protected Session getSession(Serializable id) {
+        if (!isValid(id)) {
+            String msg = "Specified id [" + id + "] does not correspond to a valid Session  It either " +
+                    "does not exist or the corresponding session has been stopped or expired.";
+            throw new InvalidSessionException(msg, id);
+        }
 
+        return new DelegatingSession(this, id);
+    }
+
+    protected Subject createSubject() {
         Serializable sessionId = getCurrentSessionId();
+        Session session = null;
         if (sessionId != null) {
             try {
-                subject = getSubjectBySessionId(sessionId);
+                session = getSession(sessionId);
             } catch (InvalidSessionException e) {
                 if (log.isDebugEnabled()) {
                     log.debug("Session id referenced on the current thread [" + sessionId + "] is invalid.  " +
@@ -218,12 +222,22 @@
             }
         }
 
-        if (subject == null) {
-            PrincipalCollection principals = getRememberedIdentity();
-            return getSubjectFactory().createSubject(principals, null, false, null);
+        PrincipalCollection principals = getRememberedIdentity();
+        return createSubject(principals, session);
+    }
+
+    protected Subject createSubject(PrincipalCollection principals, Session session) {
+        Map<String, Object> context = new HashMap<String, Object>(2);
+
+        if (principals != null && !principals.isEmpty()) {
+            context.put(SubjectFactory.PRINCIPALS, principals);
+        }
+        if (session != null) {
+            context.put(SubjectFactory.SESSION, session);
         }
 
-        return subject;
+        SubjectFactory sf = getSubjectFactory();
+        return sf.createSubject(context);
     }
 
     /**
@@ -235,12 +249,20 @@
      *         authenticated user.
      */
     protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info) {
-        return getSubjectFactory().createSubject(token, info, getSubject(false));
+        Map<String, Object> context = new HashMap<String, Object>();
+        context.put(SubjectFactory.AUTHENTICATED, Boolean.TRUE);
+        context.put(SubjectFactory.AUTHENTICATION_TOKEN, token);
+        context.put(SubjectFactory.AUTHENTICATION_INFO, info);
+        Subject subject = getSubject(false);
+        if (subject != null) {
+            context.put(SubjectFactory.SUBJECT, subject);
+        }
+        return getSubjectFactory().createSubject(context);
     }
 
     /**
      * Binds a <tt>Subject</tt> instance created after authentication to the application for later use.
-     *
+     * <p/>
      * <p>The default implementation merely binds the argument to the thread local via the {@link ThreadContext}.
      * Should be overridden by subclasses for environment-specific binding (e.g. web environment, etc).
      *
@@ -317,7 +339,7 @@
     /**
      * First authenticates the <tt>AuthenticationToken</tt> argument, and if successful, constructs a
      * <tt>Subject</tt> instance representing the authenticated account's identity.
-     *
+     * <p/>
      * <p>Once constructed, the <tt>Subject</tt> instance is then {@link #bind bound} to the application for
      * subsequent access before being returned to the caller.
      *
@@ -359,6 +381,13 @@
         rememberMeLogout(subjectIdentifier);
     }
 
+    /**
+     * @since 1.0
+     */
+    public Subject getSubject(Map context) {
+        return getSubjectFactory().createSubject(context);
+    }
+
     protected Subject getSubject(PrincipalCollection principals) {
         //Method arg is ignored at the moment - retrieve from the environment if it exists:
         return getSubject(false);
@@ -449,29 +478,17 @@
         return getSubject(true);
     }
 
-    protected PrincipalCollection getPrincipals(Session session) {
-        return (PrincipalCollection) session.getAttribute(SessionSubjectBinder.PRINCIPALS_SESSION_KEY);
-    }
-
-    protected boolean isAuthenticated(Session session, PrincipalCollection principals) {
-        if (principals != null) {
-            Boolean authc = (Boolean) session.getAttribute(SessionSubjectBinder.AUTHENTICATED_SESSION_KEY);
-            return authc != null && authc;
-        }
-        return false;
-    }
-
     /**
      * Acquires the {@link Subject Subject} that owns the {@link Session Session} with the specified {@code sessionId}.
-     *
-     * <p><b>Although simple in concept, this method provides incredibly powerful functionality:</b>
-     *
-     * <p>The ability to reference a {@code Subject} and their server-side session
+     * <p/>
+     * <b>Although simple in concept, this method provides incredibly powerful functionality:</b>
+     * <p/>
+     * The ability to reference a {@code Subject} and their server-side session
      * <em>across clients of different mediums</em> such as web applications, Java applets,
      * standalone C# clients over XMLRPC and/or SOAP, and many others. This is a <em>huge</em>
      * benefit in heterogeneous enterprise applications.
-     *
-     * <p>To maintain session integrity across client mediums, the {@code sessionId} <b>must</b> be transmitted
+     * <p/>
+     * To maintain session integrity across client mediums, the {@code sessionId} <b>must</b> be transmitted
      * to all client mediums securely (e.g. over SSL) to prevent man-in-the-middle attacks.  This
      * is nothing new - all web applications are susceptible to the same problem when transmitting
      * {@code Cookie}s or when using URL rewriting.  As long as the
@@ -493,17 +510,12 @@
      * @since 1.0
      */
     private Subject getSubjectBySessionId(Serializable sessionId) throws InvalidSessionException, AuthorizationException {
-        if (!isValid(sessionId)) {
-            String msg = "Specified id [" + sessionId + "] does not correspond to a valid Session  It either " +
-                    "does not exist or the corresponding session has been stopped or expired.";
-            throw new InvalidSessionException(msg, sessionId);
-        }
+        Session session = getSession(sessionId);
 
-        Session existing = new DelegatingSession(this, sessionId);
-        PrincipalCollection principals = getPrincipals(existing);
-        boolean authenticated = isAuthenticated(existing, principals);
-        InetAddress host = existing.getHostAddress();
+        Map<String, Object> context = new HashMap<String, Object>(1);
+        context.put(SubjectFactory.SESSION, session);
 
-        return getSubjectFactory().createSubject(principals, existing, authenticated, host);
+        SubjectFactory sf = getSubjectFactory();
+        return sf.createSubject(context);
     }
 }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSubjectFactory.java Wed Jul 22 01:11:54 2009
@@ -18,8 +18,6 @@
  */
 package org.apache.shiro.mgt;
 
-import java.net.InetAddress;
-
 import org.apache.shiro.authc.AuthenticationInfo;
 import org.apache.shiro.authc.AuthenticationToken;
 import org.apache.shiro.authc.InetAuthenticationToken;
@@ -29,6 +27,9 @@
 import org.apache.shiro.subject.Subject;
 import org.apache.shiro.util.ThreadContext;
 
+import java.net.InetAddress;
+import java.util.Map;
+
 
 /**
  * Default {@link SubjectFactory SubjectFactory} implementation that creates {@link DelegatingSubject DelegatingSubject}
@@ -56,6 +57,22 @@
         this.securityManager = securityManager;
     }
 
+    @SuppressWarnings({"unchecked"})
+    protected static <E> E getTypedValue(Map context, String key, Class<E> type) {
+        E found = null;
+        Object o = context.get(key);
+        if (o != null) {
+            if (!type.isAssignableFrom(o.getClass())) {
+                String msg = "Invalid object found in context Map under key [" + key + "].  Expected type " +
+                        "was [" + type.getName() + "], but the object under that key is of type " +
+                        "[" + o.getClass().getName() + "].";
+                throw new IllegalArgumentException(msg);
+            }
+            found = (E) o;
+        }
+        return found;
+    }
+
     private void assertPrincipals(AuthenticationInfo info) {
         PrincipalCollection principals = info.getPrincipals();
         if (principals == null || principals.isEmpty()) {
@@ -64,29 +81,104 @@
         }
     }
 
-    public Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing) {
-        assertPrincipals(info);
+    protected boolean isAuthenticationContext(Map context) {
+        return context.containsKey(SubjectFactory.AUTHENTICATION_TOKEN);
+    }
+
+    protected static boolean isEmpty(PrincipalCollection principals) {
+        return principals == null || principals.isEmpty();
+    }
+
+    protected PrincipalCollection getPrincipals(Map context, Session session) {
+        PrincipalCollection principals = getTypedValue(context, SubjectFactory.PRINCIPALS, PrincipalCollection.class);
+
+        if (isEmpty(principals)) {
+            //check to see if they were just authenticated:
+            AuthenticationInfo info = getTypedValue(context, SubjectFactory.AUTHENTICATION_INFO, AuthenticationInfo.class);
+            if (info != null) {
+                principals = info.getPrincipals();
+            }
+        }
+
+        if (isEmpty(principals)) {
+            Subject subject = getTypedValue(context, SubjectFactory.SUBJECT, Subject.class);
+            if (subject != null) {
+                principals = subject.getPrincipals();
+            }
+        }
+
+        if (isEmpty(principals)) {
+            //try the session:
+            if (session != null) {
+                principals = (PrincipalCollection) session.getAttribute(SessionSubjectBinder.PRINCIPALS_SESSION_KEY);
+            }
+        }
+
+        return principals;
+    }
+
+    protected Session getSession(Map context) {
+        Session session = getTypedValue(context, SubjectFactory.SESSION, Session.class);
 
-        //get any existing session that may exist - we don't want to lose it:
-        Session session = null;
-        if (existing != null) {
-            session = existing.getSession(false);
+        if (session == null) {
+            //try the Subject if it exists:
+            Subject existingSubject = getTypedValue(context, SubjectFactory.SUBJECT, Subject.class);
+            if (existingSubject != null) {
+                session = existingSubject.getSession(false);
+            }
         }
 
-        InetAddress authcSourceIP = null;
-        if (token instanceof InetAuthenticationToken) {
-            authcSourceIP = ((InetAuthenticationToken) token).getInetAddress();
+        return session;
+    }
+
+    protected InetAddress getInetAddress(Map context, Session session) {
+        InetAddress inet = getTypedValue(context, SubjectFactory.INET_ADDRESS, InetAddress.class);
+
+        if (inet == null) {
+            //check to see if there is an AuthenticationToken from which to retrieve it:
+            AuthenticationToken token = getTypedValue(context, SubjectFactory.AUTHENTICATION_TOKEN, AuthenticationToken.class);
+            if (token instanceof InetAuthenticationToken) {
+                inet = ((InetAuthenticationToken) token).getInetAddress();
+            }
         }
-        if (authcSourceIP == null) {
-            //try the thread local:
-            authcSourceIP = ThreadContext.getInetAddress();
+
+        if (inet == null) {
+            if (session != null) {
+                inet = session.getHostAddress();
+            }
+        }
+
+        if (inet == null) {
+            //fall back to the thread local if it exists:
+            inet = ThreadContext.getInetAddress();
         }
 
-        return createSubject(info.getPrincipals(), session, true, authcSourceIP);
+        return inet;
+    }
+
+    protected boolean isAuthenticated(Map context, Session session) {
+        Boolean authc = getTypedValue(context, SubjectFactory.AUTHENTICATED, Boolean.class);
+        if (authc == null) {
+            //see if there is an AuthenticationInfo object.  If so, the very presence of one indicates a successful
+            //authentication attempt:
+            AuthenticationInfo info = getTypedValue(context, SubjectFactory.AUTHENTICATION_INFO, AuthenticationInfo.class);
+            authc = info != null;
+        }
+        if (!authc) {
+            //fall back to a session check:
+            if (session != null) {
+                Boolean sessionAuthc = (Boolean) session.getAttribute(SessionSubjectBinder.AUTHENTICATED_SESSION_KEY);
+                authc = sessionAuthc != null && sessionAuthc;
+            }
+        }
+        return authc;
     }
 
-    public Subject createSubject(PrincipalCollection principals, Session existing,
-                                 boolean authenticated, InetAddress inetAddress) {
-        return new DelegatingSubject(principals, authenticated, inetAddress, existing, getSecurityManager());
+    public Subject createSubject(Map context) {
+        Session session = getSession(context);
+        PrincipalCollection principals = getPrincipals(context, session);
+        boolean authenticated = isAuthenticated(context, session);
+        InetAddress inet = getInetAddress(context, session);
+        return new DelegatingSubject(principals, authenticated, inet, session, getSecurityManager());
     }
 }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java Wed Jul 22 01:11:54 2009
@@ -26,6 +26,8 @@
 import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.Subject;
 
+import java.util.Map;
+
 
 /**
  * A <tt>SecurityManager</tt> executes all security operations for <em>all</em> Subjects (aka users) across a
@@ -105,6 +107,27 @@
      */
     Subject getSubject();
 
+    /**
+     * Returns the {@code Subject} instance reflecting the specified contextual data.
+     * <p/>
+     * The context can be anything needed by this {@code SecurityManager} to construct a {@code Subject} instance.
+     * Most Shiro end-users will never call this method - it exists primarily for
+     * framework development and to support any underlying {@link SubjectFactory SubjectFactory} implementations used
+     * by the {@code SecurityManager}.
+     * <h4>Usage</h4>
+     * The difference between calling this method and {@link #getSubject() getSubject()} is that the {@code Subject}
+     * instance returned from this method is not automatically 'bound' to the application
+     * for further use.  That is, after calling this method, a call to {@code getSubject()} will not necessarily return
+     * the same instance.  Callers are expected to know that {@code Subject} instances have local scope only and any
+     * other further use beyond the calling method must be managed manually.
+     *
+     * @param context any data needed to direct how the Subject should be constructed.
+     * @return the {@code Subject} instance reflecting the specified initialization data.
+     * @see SubjectFactory#createSubject(java.util.Map)
+     * @since 1.0
+     */
+    Subject getSubject(Map context);
+
     /*Subject getSubject(Map initData);
 
     Subject getSubjectBySessionId(Serializable sessionId);

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectFactory.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectFactory.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectFactory.java Wed Jul 22 01:11:54 2009
@@ -18,13 +18,9 @@
  */
 package org.apache.shiro.mgt;
 
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.subject.PrincipalCollection;
 import org.apache.shiro.subject.Subject;
 
-import java.net.InetAddress;
+import java.util.Map;
 
 /**
  * A {@code SubjectFactory} is responsible for returning {@link Subject Subject} instances as needed.
@@ -34,37 +30,29 @@
  */
 public interface SubjectFactory {
 
-    /**
-     * Returns a {@code Subject} instance reflecting the state of a <em>successful</em> authentication attempt.
-     * <p/>
-     * The '{@code existing}' {@code Subject} method argument is the {@code Subject} that executed the
-     * authentication attempt but still reflects an unauthenticated state.  The instance returned from this method
-     * is the {@code Subject} instance to use for future application use and reflects an authenticated state.
-     *
-     * @param token    the {@code AuthenticationToken} submitted during the successful authentication attempt.
-     * @param info     the {@code AuthenticationInfo} generated due to the successful authentication attempt.
-     * @param existing the {@code Subject} that executed the attempt, still in an 'unauthenticated' state.
-     * @return the {@code Subject} for the application to use going forward, but in an 'authenticated' state.
-     */
-    Subject createSubject(AuthenticationToken token, AuthenticationInfo info, Subject existing);
+    public static final String AUTHENTICATION_TOKEN = SubjectFactory.class.getName() + ".AUTHENTICATION_TOKEN";
+
+    public static final String AUTHENTICATION_INFO = SubjectFactory.class.getName() + ".AUTHENTICATION_INFO";
+
+    public static final String SUBJECT = SubjectFactory.class.getName() + ".SUBJECT";
+
+    public static final String PRINCIPALS = SubjectFactory.class.getName() + ".PRINCIPALS";
+
+    public static final String SESSION = SubjectFactory.class.getName() + ".SESSION";
+
+    public static final String AUTHENTICATED = SubjectFactory.class.getName() + ".AUTHENTICATED";
+
+    public static final String INET_ADDRESS = SubjectFactory.class.getName() + ".INET_ADDRESS";
 
     /**
-     * Returns a {@code Subject} instance reflecting the specified Subject identity (aka 'principals'), any
-     * existing {@code Session} that might be in place for that identity, whether or not the Subject is to be
-     * considered already authenticated, and the originating host from where the Subject instance to be created is
-     * being acquired.
+     * Creates a new Subject instance reflecting the state of the specified contextual data.  The data would be
+     * anything required to required to construct a {@code Subject} instance and its contents can vary based on
+     * environment.
      *
-     * @param principals      the identifying attributes of the Subject instance to be created, or
-     *                        {@code null} if the Subject's identity is unknown because they haven't logged in yet and are not 'remembered'
-     *                        from {@code RememberMe} services.
-     * @param existing        any {@link org.apache.shiro.session.Session Session} that might be in place for the specified {@link org.apache.shiro.subject.Subject}, or
-     *                        {@code null} if there is no session yet created for the specified {@code Subject}.  If non-{@code null},
-     *                        it should be retained and used by the {@code Subject} instance returned from this method call.
-     * @param authenticated   whether or not the {@code Subject} instance returned should be considered already
-     *                        authenticated.
-     * @param originatingHost the host location indicating where the {@code Subject} is located.
-     * @return a {@code Subject} instance representing the aggregate state of the specified method arguments.
+     * @param context the contextual data to be used by the implementation to construct an appropriate {@code Subject}
+     *                instance.
+     * @return a {@code Subject} instance created based on the specified context.
      */
-    Subject createSubject(PrincipalCollection principals, Session existing, boolean authenticated, InetAddress originatingHost);
+    Subject createSubject(Map context);
 
 }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java Wed Jul 22 01:11:54 2009
@@ -35,7 +35,6 @@
 
 import java.io.Serializable;
 import java.net.InetAddress;
-import java.net.UnknownHostException;
 import java.util.Collection;
 import java.util.List;
 
@@ -79,7 +78,7 @@
     protected SecurityManager securityManager;
 
     public DelegatingSubject(SecurityManager securityManager) {
-        this(null, false, getLocalHost(), null, securityManager);
+        this(null, false, null, null, securityManager);
     }
 
     public DelegatingSubject(PrincipalCollection principals, boolean authenticated, InetAddress inetAddress,
@@ -89,27 +88,16 @@
         }
         this.securityManager = securityManager;
         this.principals = principals;
-
         this.authenticated = authenticated;
 
         if (inetAddress != null) {
             this.inetAddress = inetAddress;
-        } else {
-            this.inetAddress = getLocalHost();
         }
         if (session != null) {
             this.session = decorate(session);
         }
     }
 
-    protected static InetAddress getLocalHost() {
-        try {
-            return InetAddress.getLocalHost();
-        } catch (UnknownHostException e) {
-            return null;
-        }
-    }
-
     protected Session decorate(Session session) {
         if (session == null) {
             throw new IllegalArgumentException("session cannot be null");

Modified: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DefaultSessionManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DefaultSessionManagerTest.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DefaultSessionManagerTest.java (original)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DefaultSessionManagerTest.java Wed Jul 22 01:11:54 2009
@@ -1,3 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.shiro.session.mgt;
 
 import org.apache.shiro.util.ThreadContext;
@@ -42,7 +60,7 @@
         sm.setGlobalSessionTimeout(100);
         Serializable sessionId = sm.start((InetAddress) null);
         assertTrue(sm.isValid(sessionId));
-        sleep(100);
+        sleep(150);
         assertFalse(sm.isValid(sessionId));
     }
 }

Modified: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DelegatingSessionTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DelegatingSessionTest.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DelegatingSessionTest.java (original)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DelegatingSessionTest.java Wed Jul 22 01:11:54 2009
@@ -1,10 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
 package org.apache.shiro.session.mgt;
 
-import org.junit.Before;
+import org.apache.shiro.util.ThreadContext;
 import org.junit.After;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import org.junit.Before;
 import org.junit.Test;
-import static org.junit.Assert.*;
-import org.apache.shiro.util.ThreadContext;
 
 import java.io.Serializable;
 import java.net.InetAddress;
@@ -21,7 +40,7 @@
     public void setup() {
         ThreadContext.clear();
         sm = new DefaultSessionManager();
-        Serializable sessionId = sm.start((InetAddress)null);
+        Serializable sessionId = sm.start((InetAddress) null);
         this.session = new DelegatingSession(sm, sessionId);
     }
 

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSubjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSubjectFactory.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSubjectFactory.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSubjectFactory.java Wed Jul 22 01:11:54 2009
@@ -18,18 +18,16 @@
  */
 package org.apache.shiro.web;
 
-import java.net.InetAddress;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
 import org.apache.shiro.mgt.DefaultSubjectFactory;
 import org.apache.shiro.mgt.SecurityManager;
 import org.apache.shiro.mgt.SessionSubjectBinder;
 import org.apache.shiro.session.Session;
-import org.apache.shiro.subject.PrincipalCollection;
-import org.apache.shiro.subject.Subject;
 import org.apache.shiro.web.session.WebSessionManager;
 
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.util.Map;
+
 
 /**
  * @author Les Hazlewood
@@ -62,33 +60,10 @@
         this.webSessionManager = webSessionManager;
     }
 
-    protected PrincipalCollection getPrincipals(Session existing) {
-        PrincipalCollection principals = null;
-        if (existing != null) {
-            principals = (PrincipalCollection) existing.getAttribute(PRINCIPALS_SESSION_KEY);
-        }
-//        if (principals == null) {
-//            //check remember me:
-//            principals = getRememberedIdentity();
-//            if (principals != null && existing != null) {
-//                existing.setAttribute(PRINCIPALS_SESSION_KEY, principals);
-//            }
-//        }
-        return principals;
-    }
-
-    protected boolean isAuthenticated(Session session) {
-        Boolean value = null;
-        if (session != null) {
-            value = (Boolean) session.getAttribute(AUTHENTICATED_SESSION_KEY);
-        }
-        return value != null && value;
-    }
-
     protected Session getWebSession() {
         ServletRequest request = WebUtils.getServletRequest();
         ServletResponse response = WebUtils.getServletResponse();
-        if ( request == null || response == null ) {
+        if (request == null || response == null) {
             //no current web request - probably a remote method invocation that didn't come in via a servlet request:
             return null;
         } else {
@@ -97,31 +72,11 @@
     }
 
     @Override
-    public Subject createSubject(PrincipalCollection principals, Session existing, boolean authenticated, InetAddress inetAddress) {
-        Session session = existing;
+    protected Session getSession(Map context) {
+        Session session = super.getSession(context);
         if (session == null) {
             session = getWebSession();
         }
-
-        PrincipalCollection pc = principals;
-        if (pc == null) {
-            pc = getPrincipals(session);
-        }
-
-        boolean authc = authenticated;
-        if (!authc) {
-            //check session to be sure:
-            authc = isAuthenticated(session);
-        }
-
-        InetAddress inet = inetAddress;
-        if (inet == null) {
-            ServletRequest request = WebUtils.getServletRequest();
-            if ( request != null ) {
-                inet = WebUtils.getInetAddress(request);
-            }
-        }
-
-        return super.createSubject(pc, session, authc, inet);
+        return session;
     }
 }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java Wed Jul 22 01:11:54 2009
@@ -329,9 +329,17 @@
 
     protected void onStop(Session session) {
         super.onStop(session);
+        removeSessionIdCookie();
+    }
+
+    protected void onExpiration(Session session) {
+        super.onExpiration(session);
+        removeSessionIdCookie();
+    }
+
+    protected void removeSessionIdCookie() {
         ServletRequest request = WebUtils.getRequiredServletRequest();
         ServletResponse response = WebUtils.getRequiredServletResponse();
         removeSessionIdCookie(request, response);
-        getSessionIdCookieAttribute().removeValue(request, response);
     }
 }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DelegatingWebSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DelegatingWebSessionManager.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DelegatingWebSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DelegatingWebSessionManager.java Wed Jul 22 01:11:54 2009
@@ -21,11 +21,9 @@
 import org.apache.shiro.session.InvalidSessionException;
 import org.apache.shiro.session.Session;
 import org.apache.shiro.session.mgt.DelegatingSession;
-import org.apache.shiro.session.mgt.SessionFactory;
 import org.apache.shiro.session.mgt.SessionManager;
 
 import java.io.Serializable;
-import java.net.InetAddress;
 import java.util.Map;
 
 /**
@@ -46,6 +44,9 @@
  */
 public class DelegatingWebSessionManager extends DefaultWebSessionManager {
 
+    private static final String THREAD_CONTEXT_SESSION_KEY =
+            DelegatingWebSessionManager.class.getName() + ".THREAD_CONTEXT_SESSION_KEY";
+
     private SessionManager delegateSessionManager = null;
 
     public DelegatingWebSessionManager() {
@@ -84,11 +85,7 @@
     @Override
     protected Session doCreateSession(Map initData) {
         assertDelegateExists();
-        InetAddress host = null;
-        if (initData != null && initData.containsKey(SessionFactory.ORIGINATING_HOST_KEY)) {
-            host = (InetAddress) initData.get(SessionFactory.ORIGINATING_HOST_KEY);
-        }
-        Serializable sessionId = this.delegateSessionManager.start(host);
+        Serializable sessionId = this.delegateSessionManager.start(initData);
         return new DelegatingSession(this, sessionId);
     }
 
@@ -100,15 +97,36 @@
 
     @Override
     protected Session retrieveSessionFromDataSource(Serializable id) throws InvalidSessionException {
+        /*Session session = (Session)ThreadContext.get(THREAD_CONTEXT_SESSION_KEY);
+        if ( session != null ) {
+            return session;
+        }*/
         assertDelegateExists();
         this.delegateSessionManager.checkValid(id);
-        //we need the DelegatingSession to reference the delegateSessionManager and not 'this' so
-        //we avoid an infinite loop:
         return new DelegatingSession(this.delegateSessionManager, id);
+        /*//we need the DelegatingSession to reference the delegateSessionManager and not 'this' so
+        //we avoid an infinite loop:
+        session = new DelegatingSession(this.delegateSessionManager, id);
+        ThreadContext.put(THREAD_CONTEXT_SESSION_KEY, session);
+        
+        return session;*/
+    }
+
+    @Override
+    protected void onChange(Session session) {
+        //do nothing - back-end will react to change as appropriate
     }
 
     @Override
     protected void doValidate(Session session) throws InvalidSessionException {
-        session.touch();
+        /*if ( session == null ) {
+            throw new InvalidSessionException("Session method argument is null!" );
+        }
+        Serializable id = session.getId();
+        if ( id == null ) {
+            throw new InvalidSessionException("Session does not have an id!" );
+        }
+        assertDelegateExists();
+        this.delegateSessionManager.checkValid(id);*/
     }
 }

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DelegatingWebSecurityManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DelegatingWebSecurityManagerTest.java?rev=796597&r1=796596&r2=796597&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DelegatingWebSecurityManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DelegatingWebSecurityManagerTest.java Wed Jul 22 01:11:54 2009
@@ -1,31 +1,26 @@
 package org.apache.shiro.web;
 
-import org.junit.Before;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.mgt.DefaultSecurityManager;
+import org.apache.shiro.realm.text.PropertiesRealm;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.util.ThreadContext;
+import static org.easymock.EasyMock.*;
 import org.junit.After;
-import org.junit.Test;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
-import org.apache.shiro.util.ThreadContext;
-import org.apache.shiro.subject.Subject;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.session.mgt.DefaultSessionManager;
-import org.apache.shiro.realm.text.PropertiesRealm;
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.mgt.DefaultSecurityManager;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
+import org.junit.Before;
+import org.junit.Test;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.Serializable;
 
 /**
- * Created by IntelliJ IDEA.
- * User: lhazlewood
- * Date: Jul 18, 2009
- * Time: 7:46:22 PM
- * To change this template use File | Settings | File Templates.
+ * Unit test for the {@link org.apache.shiro.web.DelegatingWebSecurityManager} implementation.
+ *
+ * @since 1.0
  */
 public class DelegatingWebSecurityManagerTest {
 
@@ -36,7 +31,6 @@
     public void setup() {
         delegate = new DefaultSecurityManager();
         delegate.setRealm(new PropertiesRealm());
-        delegate.setGlobalSessionTimeout(-1);
         sm = new DelegatingWebSecurityManager();
         sm.setDelegateSecurityManager(delegate);
         SecurityUtils.setSecurityManager(sm);
@@ -60,7 +54,8 @@
 
     @Test
     public void testSessionTimeout() {
-        long globalTimeout = -1;
+        long globalTimeout = 100;
+        delegate.setGlobalSessionTimeout(globalTimeout);
 
         HttpServletRequest mockRequest = createNiceMock(HttpServletRequest.class);
         WebUtils.bind(mockRequest);
@@ -75,15 +70,13 @@
         Subject subject = sm.getSubject();
         Session session = subject.getSession();
         Serializable origId = session.getId();
-        assertEquals(session.getTimeout(), globalTimeout);
-        session.setTimeout(100);
-        assertEquals(session.getTimeout(), 100);
-        sleep(150);
+        assertEquals(globalTimeout, session.getTimeout());
+        session.setTimeout(125);
+        assertEquals(125, session.getTimeout());
+        sleep(175);
         //now the underlying session should have been expired and a new one replaced by default.
         //so ensure the replaced session has the default session timeout:
-        assertEquals(session.getTimeout(), globalTimeout);
+        assertEquals(globalTimeout, session.getTimeout());
         assertFalse(origId.equals(session.getId())); //new ID would have been generated
-
-        //verify(mockRequest);
     }
 }