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/24 01:01:20 UTC

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

Author: lhazlewood
Date: Thu Jul 23 23:01:19 2009
New Revision: 797256

URL: http://svn.apache.org/viewvc?rev=797256&view=rev
Log:
Continued work homogenizing Session access - previous work on DefaultSubjectFactory and DefaultSecurityManager allowed the removal of the WebSubjectFactory entirely.  Made minor code enhancements per IDEA inspections.  Enabled log4j as the logging mechanism for test cases, but will probably change that to be Logback so we can have one less jar dependency.  Lots of minor JavaDoc fixes

Added:
    incubator/shiro/trunk/web/src/test/resources/
    incubator/shiro/trunk/web/src/test/resources/log4j.properties
Removed:
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebSubjectFactory.java
Modified:
    incubator/shiro/trunk/core/pom.xml
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/codec/Base64.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SubjectFactory.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java
    incubator/shiro/trunk/core/src/main/java/org/apache/shiro/subject/DelegatingSubject.java
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/activedirectory/ActiveDirectoryRealmTest.java
    incubator/shiro/trunk/core/src/test/java/org/apache/shiro/session/mgt/DelegatingSessionTest.java
    incubator/shiro/trunk/core/src/test/resources/log4j.properties
    incubator/shiro/trunk/samples/spring-hibernate/src/main/java/org/apache/shiro/samples/sprhib/dao/BootstrapDataPopulator.java
    incubator/shiro/trunk/support/ehcache/pom.xml
    incubator/shiro/trunk/support/quartz/pom.xml
    incubator/shiro/trunk/support/spring/pom.xml
    incubator/shiro/trunk/web/pom.xml
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DelegatingWebSecurityManager.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.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/ServletContainerSessionManager.java
    incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DefaultWebSecurityManagerTest.java
    incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java

Modified: incubator/shiro/trunk/core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/pom.xml?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/pom.xml (original)
+++ incubator/shiro/trunk/core/pom.xml Thu Jul 23 23:01:19 2009
@@ -50,11 +50,15 @@
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
         </dependency>
     </dependencies>
 

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/codec/Base64.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/codec/Base64.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/codec/Base64.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/codec/Base64.java Thu Jul 23 23:01:19 2009
@@ -20,16 +20,16 @@
 
 /**
  * Provides Base64 encoding and decoding as defined by RFC 2045.
- *
+ * <p/>
  * <p>
  * This class implements section <cite>6.8. Base64 Content-Transfer-Encoding</cite> from RFC 2045 <cite>Multipurpose
  * Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</cite> by Freed and Borenstein.
  * </p>
- *
+ * <p/>
  * <p>This class was borrowed from Apache Commons Codec SVN repository (rev. 618419) with modifications
  * to enable Base64 conversion without a full dependecny on Commons Codec.  We didn't want to reinvent the wheel of
  * great work they've done, but also didn't want to force every Shiro user to depend on the commons-codec.jar</p>
- *
+ * <p/>
  * <p>As per the Apache 2.0 license, the original copyright notice and all author and copyright information have
  * remained in tact.</p>
  *
@@ -42,7 +42,7 @@
 
     /**
      * Chunk size per RFC 2045 section 6.8.
-     *
+     * <p/>
      * <p>The character limit does not count the trailing CRLF, but counts all other characters, including any
      * equal signs.</p>
      *
@@ -100,9 +100,9 @@
     /**
      * Contains the Base64 values <code>0</code> through <code>63</code> accessed by using character encodings as
      * indices.
-     *
+     * <p/>
      * <p>For example, <code>base64Alphabet['+']</code> returns <code>62</code>.</p>
-     *
+     * <p/>
      * <p>The value of undefined encodings is <code>-1</code>.</p>
      */
     private static final byte[] base64Alphabet = new byte[BASELENGTH];
@@ -111,9 +111,9 @@
      * <p>Contains the Base64 encodings <code>A</code> through <code>Z</code>, followed by <code>a</code> through
      * <code>z</code>, followed by <code>0</code> through <code>9</code>, followed by <code>+</code>, and
      * <code>/</code>.</p>
-     *
+     * <p/>
      * <p>This array is accessed by using character values as indices.</p>
-     *
+     * <p/>
      * <p>For example, <code>lookUpBase64Alphabet[62] </code> returns <code>'+'</code>.</p>
      */
     private static final byte[] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
@@ -161,11 +161,12 @@
     private static boolean isBase64(byte octect) {
         if (octect == PAD) {
             return true;
-        } else if (octect < 0 || base64Alphabet[octect] == -1) {
-            return false;
-        } else {
-            return true;
-        }
+        } else //noinspection RedundantIfStatement
+            if (octect < 0 || base64Alphabet[octect] == -1) {
+                return false;
+            } else {
+                return true;
+            }
     }
 
     /**
@@ -267,7 +268,7 @@
         long lengthDataBits = binaryDataLength * EIGHTBIT;
         long fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
         long tripletCount = lengthDataBits / TWENTYFOURBITGROUP;
-        long encodedDataLengthLong = 0;
+        long encodedDataLengthLong;
         int chunckCount = 0;
 
         if (fewerThan24bits != 0) {
@@ -295,11 +296,11 @@
         int encodedDataLength = (int) encodedDataLengthLong;
         byte encodedData[] = new byte[encodedDataLength];
 
-        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+        byte k, l, b1, b2, b3;
 
         int encodedIndex = 0;
-        int dataIndex = 0;
-        int i = 0;
+        int dataIndex;
+        int i;
         int nextSeparatorIndex = CHUNK_SIZE;
         int chunksSoFar = 0;
 
@@ -430,13 +431,13 @@
         }
 
         int numberQuadruple = base64Data.length / FOURBYTE;
-        byte decodedData[] = null;
-        byte b1 = 0, b2 = 0, b3 = 0, b4 = 0, marker0 = 0, marker1 = 0;
+        byte decodedData[];
+        byte b1, b2, b3, b4, marker0, marker1;
 
         // Throw away anything not in base64Data
 
         int encodedIndex = 0;
-        int dataIndex = 0;
+        int dataIndex;
         {
             // this sizes the output array properly - rlw
             int lastData = base64Data.length;
@@ -468,7 +469,7 @@
             } else if (marker0 == PAD) {
                 // Two PAD e.g. 3c[Pad][Pad]
                 decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
-            } else if (marker1 == PAD) {
+            } else {
                 // One PAD e.g. 3cQ[Pad]
                 b3 = base64Alphabet[marker0];
                 decodedData[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);

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=797256&r1=797255&r2=797256&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 Thu Jul 23 23:01:19 2009
@@ -39,32 +39,32 @@
 
 
 /**
- * <p>The Shiro framework's default concrete implementation of the {@link SecurityManager} interface,
+ * The Shiro framework's default concrete implementation of the {@link SecurityManager} interface,
  * based around a collection of {@link org.apache.shiro.realm.Realm}s.  This implementation delegates its
  * 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>
+ * implementation.
  * <p/>
- * <p>To greatly reduce and simplify configuration, this implementation (and its superclasses) will
+ * 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,
+ * {@link Realm Realm}s.  Because {@code Realm} implementations usually interact with an application's data model,
  * they are almost always application specific;  you will want to specify at least one custom
- * <tt>Realm</tt> implementation that 'knows' about your application's data/security model
+ * {@code Realm} 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>
+ * will have suitable defaults for most enterprise applications.
  * <p/>
- * <p><b>RememberMe notice</b>: This class supports the ability to configure a
+ * <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 {@code RememberMe} 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
+ * Because RememberMe services are inherently client tier-specific and
+ * therefore aplication-dependent, if you want {@code RememberMe} 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
  * {@code org.apache.shiro.web.DefaultWebSecurityManager} implementation, which
- * <em>does</em> support <tt>RememberMe</tt> services by default at startup.
+ * <em>does</em> support {@code RememberMe} services by default at startup.
  *
  * @author Les Hazlewood
  * @author Jeremy Haile
@@ -193,16 +193,11 @@
     }
 
     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);
-        }
-
+        checkValid(id);
         return new DelegatingSession(this, id);
     }
 
-    protected Subject createSubject() {
+    protected Session getCurrentSession() {
         Serializable sessionId = getCurrentSessionId();
         Session session = null;
         if (sessionId != null) {
@@ -221,31 +216,50 @@
                 }
             }
         }
+        return session;
+    }
 
-        PrincipalCollection principals = getRememberedIdentity();
-        return createSubject(principals, session);
+    protected Subject createSubject() {
+        Session session = getCurrentSession();
+        PrincipalCollection remembered = null;
+        //only obtain a remembered identity if the session does not have one:
+        if (session != null) {
+            if (session.getAttribute(SessionSubjectBinder.PRINCIPALS_SESSION_KEY) == null) {
+                remembered = getRememberedIdentity();
+            }
+        }
+        return createSubject(remembered, session);
     }
 
+    /**
+     * Returns a {@link Subject} instance that reflects the specified identity (principals), backed by the given
+     * {@link Session} instance.  Either argument can be null.
+     * <p/>
+     * This method is a convenience that assembles either argument into a context {@link Map Map} (if they are
+     * not null) and returns {@link #getSubject(java.util.Map)} using the Map as the parameter.
+     *
+     * @param principals the identity that the constructed {@code Subject} instance should have.
+     * @param session    the session to be associated with the constructed {@code Subject} instance.
+     * @return The Subject instance reflecting the specified identity (principals) and session.
+     * @since 1.0
+     */
     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);
         }
-
-        SubjectFactory sf = getSubjectFactory();
-        return sf.createSubject(context);
+        return getSubject(context);
     }
 
     /**
-     * Creates a <tt>Subject</tt> instance for the user represented by the given method arguments.
+     * Creates a {@code Subject} instance for the user represented by the given method arguments.
      *
-     * @param token the <tt>AuthenticationToken</tt> submitted for the successful authentication.
-     * @param info  the <tt>AuthenticationInfo</tt> of a newly authenticated user.
-     * @return the <tt>Subject</tt> instance that represents the user and session data for the newly
+     * @param token the {@code AuthenticationToken} submitted for the successful authentication.
+     * @param info  the {@code AuthenticationInfo} of a newly authenticated user.
+     * @return the {@code Subject} instance that represents the user and session data for the newly
      *         authenticated user.
      */
     protected Subject createSubject(AuthenticationToken token, AuthenticationInfo info) {
@@ -257,31 +271,22 @@
         if (subject != null) {
             context.put(SubjectFactory.SUBJECT, subject);
         }
-        return getSubjectFactory().createSubject(context);
+        return getSubject(context);
     }
 
     /**
-     * Binds a <tt>Subject</tt> instance created after authentication to the application for later use.
+     * Binds a {@code Subject} 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).
+     * The default implementation merely binds the argument to the thread local via the {@link ThreadContext}
+     * and overridden by subclasses for environment-specific binding (e.g. standalone application).
      *
-     * @param subject the <tt>Subject</tt> instance created after authentication to be bound to the application
+     * @param subject the {@code Subject} instance created after authentication to be bound to the application
      *                for later use.
      */
     protected void bind(Subject subject) {
         getSubjectBinder().bind(subject);
     }
 
-    private void assertCreation(Subject subject) throws IllegalStateException {
-        if (subject == null) {
-            String msg = "Programming error - please verify that you have overridden the " +
-                    getClass().getName() + ".createSubject( AuthenticationInfo info ) method to return " +
-                    "a non-null Subject instance";
-            throw new IllegalStateException(msg);
-        }
-    }
-
     protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info) {
         RememberMeManager rmm = getRememberMeManager();
         if (rmm != null) {
@@ -296,8 +301,8 @@
                 }
             }
         } else {
-            if (log.isDebugEnabled()) {
-                log.debug("This " + getClass().getName() + " instance does not have a " +
+            if (log.isTraceEnabled()) {
+                log.trace("This " + getClass().getName() + " instance does not have a " +
                         "[" + RememberMeManager.class.getName() + "] instance configured.  RememberMe services " +
                         "will not be performed for account [" + info + "].");
             }
@@ -337,15 +342,15 @@
     }
 
     /**
-     * First authenticates the <tt>AuthenticationToken</tt> argument, and if successful, constructs a
-     * <tt>Subject</tt> instance representing the authenticated account's identity.
+     * First authenticates the {@code AuthenticationToken} argument, and if successful, constructs a
+     * {@code Subject} 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
+     * Once constructed, the {@code Subject} instance is then {@link #bind bound} to the application for
      * subsequent access before being returned to the caller.
      *
      * @param token the authenticationToken to process for the login attempt.
      * @return a Subject representing the authenticated user.
-     * @throws AuthenticationException if there is a problem authenticating the specified <tt>token</tt>.
+     * @throws AuthenticationException if there is a problem authenticating the specified {@code token}.
      */
     public Subject login(AuthenticationToken token) throws AuthenticationException {
         AuthenticationInfo info;
@@ -364,7 +369,6 @@
             throw ae; //propagate
         }
         Subject subject = createSubject(token, info);
-        assertCreation(subject);
         bind(subject);
         return subject;
     }
@@ -382,10 +386,88 @@
     }
 
     /**
+     * This implementation attempts to resolve any session ID that may exist in the context argument by first
+     * passing it to the {@link #resolveSessionIfNecessary(java.util.Map) resolveSessionIfNecessary} method.  The
+     * return value from that call is then used to create the Subject instance by calling
+     * <code>{@link #getSubjectFactory() getSubjectFactory()}.{@link SubjectFactory#createSubject(java.util.Map) createSubject}(returnValue);</code>
+     *
+     * @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
      */
     public Subject getSubject(Map context) {
-        return getSubjectFactory().createSubject(context);
+        //Translate a session id if it exists into a Session object before sending to the SubjectFactory
+        //The SubjectFactory should not need to know how to acquire sessions as it is often environment
+        //specific - better to shield the SF from these details:
+        Map resolved = resolveSessionIfNecessary(context);
+        return getSubjectFactory().createSubject(resolved);
+    }
+
+    /**
+     * Attempts to resolve any session id in the context to its corresponding {@link Session} and returns a
+     * context that represents this resolved {@code Session} to ensure it may be referenced if necessary by the
+     * invoked {@link SubjectFactory} that performs actual {@link Subject} construction.
+     * <p/>
+     * The session id, if it exists in the context map, should be available as a value under the
+     * <code>{@link SubjectFactory SubjectFactory}.{@link SubjectFactory#SESSION_ID SESSION_ID}</code> key constant.
+     * If a session is resolved, a copy of the original context Map is made to ensure the method argument is not
+     * changed, the resolved session is placed into the copy and the copy is returned.
+     * <p/>
+     * If there is a {@code Session} already in the context because that is what the caller wants to be used for
+     * {@code Subject} construction, or if no session is resolved, this method effectively does nothing and immediately
+     * returns the Map method argument without change.
+     *
+     * @param context the subject context data that may contain a session id that should be converted to a Session instance.
+     * @return The context Map to use to pass to a {@link SubjectFactory} for subject creation.
+     * @since 1.0
+     */
+    @SuppressWarnings({"unchecked"})
+    protected Map resolveSessionIfNecessary(Map context) {
+        if (context.containsKey(SubjectFactory.SESSION)) {
+            log.debug("Context already contains a session.  Returning.");
+            return context;
+        }
+        log.trace("No session found in context.  Looking for a session id to resolve in to a session.");
+        //otherwise try to resolve a session if a session id exists:
+        Map copy = new HashMap(context);
+        Serializable sessionId = getSessionId(context);
+        if (sessionId != null) {
+            try {
+                Session session = getSession(sessionId);
+                copy.put(SubjectFactory.SESSION, session);
+            } catch (InvalidSessionException e) {
+                onInvalidSessionId(sessionId);
+                log.debug("Context referenced sessionId is invalid.  Ignoring and creating an anonymous " +
+                        "(session-less) Subject instance.", e);
+            }
+        }
+        return copy;
+    }
+
+    /**
+     * Allows subclasses to react to the fact that a provided session id was invalid.
+     *
+     * @param sessionId the session id that was discovered to be invalid (no session, expired, etc).
+     * @since 1.0
+     */
+    protected void onInvalidSessionId(Serializable sessionId) {
+    }
+
+    /**
+     * Utility method to retrieve the session id from the given subject context Map which will be used to resolve
+     * to a {@link Session} or {@code null} if there is no session id in the map.  If the session id exists, it is
+     * expected to be available in the map under the
+     * <code>{@link SubjectFactory SubjectFactory}.{@link SubjectFactory#SESSION_ID SESSION_ID}</code> constant.
+     *
+     * @param subjectContext the context map with data that will be used to construct a {@link Subject} instance via
+     *                       a {@link SubjectFactory}
+     * @return a session id to resolve to a {@link Session} instance or {@code null} if a session id could not be found.
+     * @see #getSubject(java.util.Map)
+     * @see SubjectFactory#createSubject(java.util.Map)
+     */
+    protected Serializable getSessionId(Map subjectContext) {
+        return (Serializable) subjectContext.get(SubjectFactory.SESSION_ID);
     }
 
     protected Subject getSubject(PrincipalCollection principals) {
@@ -398,6 +480,9 @@
         Subject subject;
 
         if (principals != null) {
+            if (log.isDebugEnabled()) {
+                log.debug("Logging out subject with primary id {}" + principals.iterator().next());
+            }
             beforeLogout(principals);
             Authenticator authc = getAuthenticator();
             if (authc instanceof LogoutAware) {
@@ -407,6 +492,9 @@
         } else {
             subject = getSubject(false);
         }
+        if (subject == null) {
+            return;
+        }
 
         try {
             unbind(subject);
@@ -425,7 +513,6 @@
                     log.debug(msg, e);
                 }
             }
-
         }
     }
 
@@ -496,26 +583,21 @@
      *
      * @param sessionId the id of the session that backs the desired Subject being acquired.
      * @return the {@code Subject} that owns the {@code Session Session} with the specified {@code sessionId}
-     * @throws org.apache.shiro.session.InvalidSessionException
-     *          if the session identified by <tt>sessionId</tt> has
-     *          been stopped, expired, or doesn't exist.
-     * @throws org.apache.shiro.authz.AuthorizationException
-     *          if the executor of this method is not allowed to acquire the owning {@code Subject}.  The reason
-     *          for the exception is implementation-specific and could be for any number of reasons.  A common
-     *          reason in many systems would be if one host tried to acquire a {@code Subject} based on a
-     *          {@code Session} that originated on an entirely different host (although it is not a Shiro
-     *          requirement this scenario is disallowed - its just an example that <em>may</em> throw an Exception in
-     *          some systems).
+     * @throws InvalidSessionException if the session identified by {@code sessionId} has been stopped, expired, or
+     *                                 doesn't exist.
+     * @throws AuthorizationException  if the executor of this method is not allowed to acquire the owning
+     *                                 {@code Subject}.  The reason for the exception is implementation-specific and
+     *                                 could be for any number of reasons.  A common reason in many systems would be
+     *                                 if one host tried to acquire a {@code Subject} based on a {@code Session} that
+     *                                 originated on an entirely different host (although it is not a Shiro requirement
+     *                                 this scenario is disallowed - its just an example that <em>may</em> throw an
+     *                                 Exception in some systems).
      * @see org.apache.shiro.authz.HostUnauthorizedException
      * @since 1.0
      */
     protected Subject getSubjectBySessionId(Serializable sessionId) throws InvalidSessionException, AuthorizationException {
-        Session session = getSession(sessionId);
-
         Map<String, Object> context = new HashMap<String, Object>(1);
-        context.put(SubjectFactory.SESSION, session);
-
-        SubjectFactory sf = getSubjectFactory();
-        return sf.createSubject(context);
+        context.put(SubjectFactory.SESSION_ID, sessionId);
+        return getSubject(context);
     }
 }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SessionSubjectBinder.java Thu Jul 23 23:01:19 2009
@@ -77,8 +77,8 @@
 
     @Override
     public void bind(Subject subject) {
-        bindToSession(subject);
         super.bind(subject);
+        bindToSession(subject);
     }
 
     protected void bindToSession(Subject subject) {

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=797256&r1=797255&r2=797256&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 Thu Jul 23 23:01:19 2009
@@ -30,6 +30,8 @@
  */
 public interface SubjectFactory {
 
+    public static final String SESSION_ID = SubjectFactory.class.getName() + ".SESSION_ID";
+
     public static final String AUTHENTICATION_TOKEN = SubjectFactory.class.getName() + ".AUTHENTICATION_TOKEN";
 
     public static final String AUTHENTICATION_INFO = SubjectFactory.class.getName() + ".AUTHENTICATION_INFO";

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/AbstractValidatingSessionManager.java Thu Jul 23 23:01:19 2009
@@ -158,7 +158,7 @@
         return inet;
     }
 
-    private static void assertNotNull(Session session, Serializable sessionId) throws UnknownSessionException {
+    private void assertNotNull(Session session, Serializable sessionId) throws UnknownSessionException {
         if (session == null) {
             throw new UnknownSessionException(sessionId);
         }
@@ -180,6 +180,7 @@
             validate(s);
             return s;
         } catch (InvalidSessionException ise) {
+            onInvalidSessionId(sessionId);
             if (!isAutoCreateWhenInvalid()) {
                 throw ise;
             }
@@ -192,6 +193,9 @@
         }
     }
 
+    protected void onInvalidSessionId(Serializable id) {
+    }
+
     /**
      * Looks up a session from the underlying data store based on the specified {@code sessionId}.
      *
@@ -220,19 +224,6 @@
         }
     }
 
-    protected void onInvalidation(Session session, InvalidSessionException ise) {
-        if (ise instanceof ExpiredSessionException) {
-            onExpiration(session, (ExpiredSessionException) ise);
-            return;
-        }
-        if (log.isTraceEnabled()) {
-            log.trace("Session with id [{}] is invalid.", ise.getSessionId());
-        }
-        onStop(session);
-        notifyStop(session);
-        afterStopped(session);
-    }
-
     protected void onExpiration(Session s, ExpiredSessionException ese) {
         if (log.isTraceEnabled()) {
             log.trace("Session with id [{}] has expired.", ese.getSessionId());
@@ -242,6 +233,19 @@
         afterExpired(s);
     }
 
+    protected void onInvalidation(Session s, InvalidSessionException ise) {
+        if (ise instanceof ExpiredSessionException) {
+            onExpiration(s, (ExpiredSessionException) ise);
+            return;
+        }
+        if (log.isTraceEnabled()) {
+            log.trace("Session with id [{}] is invalid.", ise.getSessionId());
+        }
+        onStop(s);
+        notifyStop(s);
+        afterStopped(s);
+    }
+
     protected void onExpiration(Session session) {
         onChange(session);
     }

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DefaultSessionManager.java Thu Jul 23 23:01:19 2009
@@ -195,9 +195,6 @@
     }
 
     protected Session retrieveSession(Serializable sessionId) throws InvalidSessionException {
-        if (log.isTraceEnabled()) {
-            log.trace("Attempting to retrieve session with id [" + sessionId + "]");
-        }
         return retrieveSessionFromDataSource(sessionId);
     }
 

Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/session/mgt/DelegatingSession.java Thu Jul 23 23:01:19 2009
@@ -18,15 +18,15 @@
  */
 package org.apache.shiro.session.mgt;
 
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.ReplacedSessionException;
+import org.apache.shiro.session.Session;
+
 import java.io.Serializable;
 import java.net.InetAddress;
 import java.util.Collection;
-import java.util.Date;
 import java.util.Collections;
-
-import org.apache.shiro.session.InvalidSessionException;
-import org.apache.shiro.session.ReplacedSessionException;
-import org.apache.shiro.session.Session;
+import java.util.Date;
 
 /**
  * A DelegatingSession is a client-tier representation of a server side
@@ -55,8 +55,10 @@
     private Date startTimestamp = null;
     private InetAddress hostAddress = null;
 
-    /** Handle to a server-side SessionManager.  See {@link #setSessionManager} for details. */
-    private SessionManager sessionManager = null;
+    /**
+     * Handle to a server-side SessionManager.  See {@link #setSessionManager} for details.
+     */
+    private transient SessionManager sessionManager = null;
 
 
     public DelegatingSession() {
@@ -109,12 +111,16 @@
         this.id = id;
     }
 
-    /** @see org.apache.shiro.session.Session#getId() */
+    /**
+     * @see org.apache.shiro.session.Session#getId()
+     */
     public Serializable getId() {
         return id;
     }
 
-    /** @see org.apache.shiro.session.Session#getStartTimestamp() */
+    /**
+     * @see org.apache.shiro.session.Session#getStartTimestamp()
+     */
     public Date getStartTimestamp() {
         if (startTimestamp == null) {
             try {
@@ -127,7 +133,9 @@
         return startTimestamp;
     }
 
-    /** @see org.apache.shiro.session.Session#getLastAccessTime() */
+    /**
+     * @see org.apache.shiro.session.Session#getLastAccessTime()
+     */
     public Date getLastAccessTime() {
         //can't cache - only business pojo knows the accurate time:
         try {
@@ -156,7 +164,9 @@
         }
     }
 
-    /** @see org.apache.shiro.session.Session#getHostAddress() */
+    /**
+     * @see org.apache.shiro.session.Session#getHostAddress()
+     */
     public InetAddress getHostAddress() {
         if (hostAddress == null) {
             try {
@@ -169,7 +179,9 @@
         return hostAddress;
     }
 
-    /** @see org.apache.shiro.session.Session#touch() */
+    /**
+     * @see org.apache.shiro.session.Session#touch()
+     */
     public void touch() throws InvalidSessionException {
         try {
             sessionManager.touch(id);
@@ -179,7 +191,9 @@
         }
     }
 
-    /** @see org.apache.shiro.session.Session#stop() */
+    /**
+     * @see org.apache.shiro.session.Session#stop()
+     */
     public void stop() throws InvalidSessionException {
         try {
             sessionManager.stop(id);
@@ -190,7 +204,9 @@
         }
     }
 
-    /** @see org.apache.shiro.session.Session#getAttributeKeys */
+    /**
+     * @see org.apache.shiro.session.Session#getAttributeKeys
+     */
     @SuppressWarnings({"unchecked"})
     public Collection<Object> getAttributeKeys() throws InvalidSessionException {
         try {
@@ -202,7 +218,9 @@
         }
     }
 
-    /** @see org.apache.shiro.session.Session#getAttribute(Object key) */
+    /**
+     * @see org.apache.shiro.session.Session#getAttribute(Object key)
+     */
     public Object getAttribute(Object key) throws InvalidSessionException {
         try {
             return sessionManager.getAttribute(id, key);
@@ -213,7 +231,9 @@
         }
     }
 
-    /** @see Session#setAttribute(Object key, Object value) */
+    /**
+     * @see Session#setAttribute(Object key, Object value)
+     */
     public void setAttribute(Object key, Object value) throws InvalidSessionException {
         if (value == null) {
             removeAttribute(key);
@@ -227,7 +247,9 @@
         }
     }
 
-    /** @see Session#removeAttribute(Object key) */
+    /**
+     * @see Session#removeAttribute(Object key)
+     */
     public Object removeAttribute(Object key) throws InvalidSessionException {
         try {
             return sessionManager.removeAttribute(id, key);

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=797256&r1=797255&r2=797256&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 Thu Jul 23 23:01:19 2009
@@ -75,7 +75,7 @@
     protected InetAddress inetAddress = null;
     protected Session session = null;
 
-    protected SecurityManager securityManager;
+    protected transient SecurityManager securityManager;
 
     public DelegatingSubject(SecurityManager securityManager) {
         this(null, false, null, null, securityManager);

Modified: incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/activedirectory/ActiveDirectoryRealmTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/activedirectory/ActiveDirectoryRealmTest.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/activedirectory/ActiveDirectoryRealmTest.java (original)
+++ incubator/shiro/trunk/core/src/test/java/org/apache/shiro/realm/activedirectory/ActiveDirectoryRealmTest.java Thu Jul 23 23:01:19 2009
@@ -18,23 +18,8 @@
  */
 package org.apache.shiro.realm.activedirectory;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.HashSet;
-import java.util.Set;
-import javax.naming.NamingException;
-
-import org.junit.After;
-import static org.junit.Assert.assertTrue;
-import org.junit.Before;
-import org.junit.Test;
-
 import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authc.AuthenticationException;
-import org.apache.shiro.authc.AuthenticationInfo;
-import org.apache.shiro.authc.AuthenticationToken;
-import org.apache.shiro.authc.SimpleAccount;
-import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.authc.*;
 import org.apache.shiro.authc.credential.CredentialsMatcher;
 import org.apache.shiro.authz.AuthorizationInfo;
 import org.apache.shiro.authz.SimpleAuthorizationInfo;
@@ -47,11 +32,21 @@
 import org.apache.shiro.subject.SimplePrincipalCollection;
 import org.apache.shiro.subject.Subject;
 import org.apache.shiro.util.ThreadContext;
+import org.junit.After;
+import static org.junit.Assert.assertTrue;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.naming.NamingException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashSet;
+import java.util.Set;
 
 
 /**
  * Simple test case for ActiveDirectoryRealm.
- *
+ * <p/>
  * todo:  While the original incarnation of this test case does not actually test the
  * heart of ActiveDirectoryRealm (no meaningful implemenation of queryForLdapAccount, etc) it obviously should.
  * This version was intended to mimic my current usage scenario in an effort to debug upgrade issues which were not related
@@ -104,8 +99,6 @@
         UserIdPrincipal userIdPrincipal = subject.getPrincipals().oneByType(UserIdPrincipal.class);
         assertTrue(userIdPrincipal.getUserId() == USER_ID);
 
-        Object principals = subject.getPrincipal();
-
         assertTrue(realm.hasRole(subject.getPrincipals(), ROLE));
 
         subject.logout();

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=797256&r1=797255&r2=797256&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 Thu Jul 23 23:01:19 2009
@@ -63,7 +63,7 @@
         Serializable origId = session.getId();
         assertEquals(session.getTimeout(), AbstractSessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT);
         session.setTimeout(100);
-        assertEquals(session.getTimeout(), 100);
+        assertEquals(100, session.getTimeout());
         sleep(150);
         //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:

Modified: incubator/shiro/trunk/core/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/test/resources/log4j.properties?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/test/resources/log4j.properties (original)
+++ incubator/shiro/trunk/core/src/test/resources/log4j.properties Thu Jul 23 23:01:19 2009
@@ -34,4 +34,5 @@
 
 log4j.logger.net.sf.ehcache=WARN
 
+log4j.logger.org.apache.shiro=TRACE
 log4j.logger.org.apache.shiro.util.ThreadContext=WARN
\ No newline at end of file

Modified: incubator/shiro/trunk/samples/spring-hibernate/src/main/java/org/apache/shiro/samples/sprhib/dao/BootstrapDataPopulator.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/samples/spring-hibernate/src/main/java/org/apache/shiro/samples/sprhib/dao/BootstrapDataPopulator.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/samples/spring-hibernate/src/main/java/org/apache/shiro/samples/sprhib/dao/BootstrapDataPopulator.java (original)
+++ incubator/shiro/trunk/samples/spring-hibernate/src/main/java/org/apache/shiro/samples/sprhib/dao/BootstrapDataPopulator.java Thu Jul 23 23:01:19 2009
@@ -34,13 +34,14 @@
 public class BootstrapDataPopulator implements InitializingBean {
 
     private DataSource dataSource;
+    @SuppressWarnings({"FieldCanBeLocal"})
     private SessionFactory sessionFactory;
 
     @Autowired
     public void setDataSource(DataSource dataSource) {
         this.dataSource = dataSource;
     }
-    
+
     // Session factory is only injected to ensure it is initialized before this runs
     @Autowired
     public void setSessionFactory(SessionFactory sessionFactory) {
@@ -52,12 +53,12 @@
         //app starts, so insert the sample admin user at startup:
         JdbcTemplate jdbcTemplate = new JdbcTemplate(this.dataSource);
 
-        jdbcTemplate.execute( "insert into roles values (1, 'user', 'The default role given to all users.')" );
-        jdbcTemplate.execute( "insert into roles values (2, 'admin', 'The administrator role only given to site admins')" );
-        jdbcTemplate.execute( "insert into roles_permissions values (2, 'user:*')" );
-        jdbcTemplate.execute( "insert into users(id,username,email,password) values (1, 'admin', 'sample@shiro.apache.org', '" + new Sha256Hash("admin").toHex() + "')" );
-        jdbcTemplate.execute( "insert into users_roles values (1, 2)" );
-        
+        jdbcTemplate.execute("insert into roles values (1, 'user', 'The default role given to all users.')");
+        jdbcTemplate.execute("insert into roles values (2, 'admin', 'The administrator role only given to site admins')");
+        jdbcTemplate.execute("insert into roles_permissions values (2, 'user:*')");
+        jdbcTemplate.execute("insert into users(id,username,email,password) values (1, 'admin', 'sample@shiro.apache.org', '" + new Sha256Hash("admin").toHex() + "')");
+        jdbcTemplate.execute("insert into users_roles values (1, 2)");
+
 
     }
 }

Modified: incubator/shiro/trunk/support/ehcache/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/ehcache/pom.xml?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/support/ehcache/pom.xml (original)
+++ incubator/shiro/trunk/support/ehcache/pom.xml Thu Jul 23 23:01:19 2009
@@ -43,11 +43,15 @@
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
         </dependency>
     </dependencies>
 

Modified: incubator/shiro/trunk/support/quartz/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/quartz/pom.xml?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/support/quartz/pom.xml (original)
+++ incubator/shiro/trunk/support/quartz/pom.xml Thu Jul 23 23:01:19 2009
@@ -43,11 +43,15 @@
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
         </dependency>
     </dependencies>
 

Modified: incubator/shiro/trunk/support/spring/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/support/spring/pom.xml?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/support/spring/pom.xml (original)
+++ incubator/shiro/trunk/support/spring/pom.xml Thu Jul 23 23:01:19 2009
@@ -52,11 +52,15 @@
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
         </dependency>
     </dependencies>
 

Modified: incubator/shiro/trunk/web/pom.xml
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/pom.xml?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/pom.xml (original)
+++ incubator/shiro/trunk/web/pom.xml Thu Jul 23 23:01:19 2009
@@ -52,11 +52,15 @@
         <!-- Test dependencies -->
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>slf4j-simple</artifactId>
+            <artifactId>jcl-over-slf4j</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
-            <artifactId>jcl-over-slf4j</artifactId>
+            <artifactId>slf4j-log4j12</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>log4j</groupId>
+            <artifactId>log4j</artifactId>
         </dependency>
     </dependencies>
 

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DefaultWebSecurityManager.java Thu Jul 23 23:01:19 2009
@@ -32,8 +32,10 @@
 import org.slf4j.LoggerFactory;
 
 import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import java.io.Serializable;
 import java.util.Collection;
+import java.util.Map;
 
 
 /**
@@ -81,13 +83,6 @@
         setRealms(realms);
     }
 
-    @Override
-    protected void afterSessionManagerSet() {
-        super.afterSessionManagerSet();
-        WebSessionManager sessionManager = (WebSessionManager) getSessionManager();
-        setSubjectFactory(new WebSubjectFactory(this, sessionManager));
-    }
-
     //TODO - yuck - create an interface
     protected WebRememberMeManager getRememberMeManagerForCookieAttributes() {
         if (!(getRememberMeManager() instanceof WebRememberMeManager)) {
@@ -242,6 +237,19 @@
     }
 
     @Override
+    protected Serializable getSessionId(Map subjectContext) {
+        Serializable sessionId = super.getSessionId(subjectContext);
+        if (sessionId == null) {
+            ServletRequest request = WebUtils.getServletRequest();
+            ServletResponse response = WebUtils.getServletResponse();
+            if (request != null && response != null) {
+                sessionId = ((WebSessionManager) getSessionManager()).getSessionId(request, response);
+            }
+        }
+        return sessionId;
+    }
+
+    @Override
     protected void beforeLogout(PrincipalCollection subjectIdentifier) {
         super.beforeLogout(subjectIdentifier);
         //also ensure a request attribute is set so the Subject is not reacquired later during the request:

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DelegatingWebSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DelegatingWebSecurityManager.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DelegatingWebSecurityManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/DelegatingWebSecurityManager.java Thu Jul 23 23:01:19 2009
@@ -64,15 +64,13 @@
      * This implementation immediately sets this instance as the
      * {@link #setAuthenticator(org.apache.shiro.authc.Authenticator) delegate authenticator} and
      * {@link #setAuthorizer(org.apache.shiro.authz.Authorizer) delegate authorizer}.  It then constructs a
-     * wrapping {@link WebSessionManager WebSubjectFactory} and {@link WebSubjectFactory WebSubjectFactory} based on
-     * the delegate {@code SecurityManager} instance and uses them as this component's
-     * {@link #setSessionManager(org.apache.shiro.session.mgt.SessionManager) sessionManager} and
-     * {@link #setSubjectFactory(org.apache.shiro.mgt.SubjectFactory) subjectFactory}, respectively.
+     * wrapping {@link WebSessionManager WebSubjectFactory} based on the delegate {@code SecurityManager} instance
+     * and uses them as this component's
+     * {@link #setSessionManager(org.apache.shiro.session.mgt.SessionManager) sessionManager} instance.
      *
      * @param delegate the {@link SecurityManager} to which all authentication, authorization, and
      *                 session management operations will be delegated.
      * @see #createWebSessionManager(org.apache.shiro.mgt.SecurityManager)
-     * @see #createWebSubjectFactory(org.apache.shiro.mgt.SecurityManager, org.apache.shiro.web.session.WebSessionManager)
      */
     public void setDelegateSecurityManager(SecurityManager delegate) {
         if (delegate == null) {
@@ -84,9 +82,6 @@
 
         WebSessionManager sessionManager = createWebSessionManager(delegate);
         setSessionManager(sessionManager);
-
-        WebSubjectFactory webSubjectFactory = createWebSubjectFactory(delegate, sessionManager);
-        setSubjectFactory(webSubjectFactory);
     }
 
     /**
@@ -100,22 +95,4 @@
     protected WebSessionManager createWebSessionManager(SecurityManager delegate) {
         return new DelegatingWebSessionManager(delegate);
     }
-
-    /**
-     * Creates a {@code WebSubjectFactory} to use when creating Subject instances for the application's use.
-     * <p/>
-     * The default implementation ignores the {@code SecurityManager} argument and merely returns
-     * <pre><code>new {@link org.apache.shiro.web.WebSubjectFactory#WebSubjectFactory(org.apache.shiro.mgt.SecurityManager, org.apache.shiro.web.session.WebSessionManager) WebSubjectFactory}(this, sessionManagerArgument);</code></pre>
-     *
-     * @param delegate       the delegate {@code SecurityManager} instance to delegate all security operations.
-     * @param sessionManager the webSessionManager created from {@link #createWebSessionManager(org.apache.shiro.mgt.SecurityManager) createWebSessionManager}(delegate);.
-     * @return the {@code WebSubjectFactory} for this {@code WebSecurityManager} to use when creating Subject instances
-     *         for the application's use.
-     * @see #setSubjectFactory(org.apache.shiro.mgt.SubjectFactory)
-     */
-    @SuppressWarnings({"UnusedDeclaration"})
-    protected WebSubjectFactory createWebSubjectFactory(SecurityManager delegate, WebSessionManager sessionManager) {
-        return new WebSubjectFactory(this, sessionManager);
-    }
-
 }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java Thu Jul 23 23:01:19 2009
@@ -18,24 +18,24 @@
  */
 package org.apache.shiro.web.servlet;
 
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLEncoder;
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpServletResponseWrapper;
 import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
 
 /**
  * HttpServletResponse implementation to support URL Encoding of Shiro Session IDs.
- *
+ * <p/>
  * It is only used when using Shiro's native Session Management configuration (and not when using the Servlet
  * Container session configuration, which is Shiro's default in a web environment).  Because the servlet container
  * already performs url encoding of its own session ids, instances of this class are only needed when using Shiro
  * native sessions.
- *
+ * <p/>
  * <p>Note that this implementation relies in part on source code from the Tomcat 6.x distribution for
  * encoding URLs for session ID URL Rewriting (we didn't want to re-invent the wheel).  Since Shiro is also
  * Apache 2.0 license, all regular licenses and conditions have remained in tact.
@@ -131,6 +131,7 @@
      * </ul>
      *
      * @param location Absolute URL to be validated
+     * @return {@code true} if the specified URL should be encoded with a session identifier, {@code false} otherwise.
      */
     protected boolean isEncodeable(final String location) {
 
@@ -154,7 +155,7 @@
 
     private boolean doIsEncodeable(HttpServletRequest hreq, HttpSession session, String location) {
         // Is this a valid absolute URL?
-        URL url = null;
+        URL url;
         try {
             url = new URL(location);
         } catch (MalformedURLException e) {
@@ -205,6 +206,7 @@
      * already absolute, return it unchanged.
      *
      * @param location URL to be (possibly) converted and then returned
+     * @return resource location as an absolute url
      * @throws IllegalArgumentException if a MalformedURLException is
      *                                  thrown when converting the relative URL to an absolute one
      */
@@ -254,6 +256,9 @@
     /**
      * Determine if the character is allowed in the scheme of a URI.
      * See RFC 2396, Section 3.1
+     *
+     * @param c the character to check
+     * @return {@code true} if the character is allowed in a URI scheme, {@code false} otherwise.
      */
     public static boolean isSchemeChar(char c) {
         return Character.isLetterOrDigit(c) ||
@@ -262,7 +267,10 @@
 
 
     /**
-     * Determine if a URI string has a <code>scheme</code> component.
+     * Returns {@code true} if the URI string has a {@code scheme} component, {@code false} otherwise.
+     *
+     * @param uri the URI string to check for a scheme component
+     * @return {@code true} if the URI string has a {@code scheme} component, {@code false} otherwise.
      */
     private boolean hasScheme(String uri) {
         int len = uri.length();
@@ -278,11 +286,11 @@
     }
 
     /**
-     * Return the specified URL with the specified session identifier
-     * suitably encoded.
+     * Return the specified URL with the specified session identifier suitably encoded.
      *
      * @param url       URL to be encoded with the session id
      * @param sessionId Session id to be included in the encoded URL
+     * @return the url with the session identifer properly encoded.
      */
     protected String toEncoded(String url, String sessionId) {
 

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java Thu Jul 23 23:01:19 2009
@@ -18,22 +18,16 @@
  */
 package org.apache.shiro.web.servlet;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.web.session.WebSession;
+
 import javax.servlet.ServletContext;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpSession;
 import javax.servlet.http.HttpSessionBindingEvent;
 import javax.servlet.http.HttpSessionBindingListener;
-import javax.servlet.http.HttpSessionContext;
-
-import org.apache.shiro.session.InvalidSessionException;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.web.session.WebSession;
+import java.util.*;
 
 
 /**
@@ -44,7 +38,6 @@
  * @author Les Hazlewood
  * @since 0.2
  */
-@SuppressWarnings({"deprecation"})
 public class ShiroHttpSession implements HttpSession {
 
     //TODO - complete JavaDoc
@@ -61,15 +54,17 @@
         }
     };
 
-    private static final HttpSessionContext HTTP_SESSION_CONTEXT = new HttpSessionContext() {
-        public HttpSession getSession(String s) {
-            return null;
-        }
-
-        public Enumeration getIds() {
-            return EMPTY_ENUMERATION;
-        }
-    };
+    @SuppressWarnings({"deprecation"})
+    private static final javax.servlet.http.HttpSessionContext HTTP_SESSION_CONTEXT =
+            new javax.servlet.http.HttpSessionContext() {
+                public HttpSession getSession(String s) {
+                    return null;
+                }
+
+                public Enumeration getIds() {
+                    return EMPTY_ENUMERATION;
+                }
+            };
 
     protected ServletContext servletContext = null;
     protected HttpServletRequest currentRequest = null;
@@ -126,7 +121,8 @@
         }
     }
 
-    public HttpSessionContext getSessionContext() {
+    @SuppressWarnings({"deprecation"})
+    public javax.servlet.http.HttpSessionContext getSessionContext() {
         return HTTP_SESSION_CONTEXT;
     }
 

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=797256&r1=797255&r2=797256&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 Thu Jul 23 23:01:19 2009
@@ -18,9 +18,6 @@
  */
 package org.apache.shiro.web.session;
 
-import org.apache.shiro.authz.AuthorizationException;
-import org.apache.shiro.authz.HostUnauthorizedException;
-import org.apache.shiro.session.InvalidSessionException;
 import org.apache.shiro.session.Session;
 import org.apache.shiro.session.mgt.DefaultSessionManager;
 import org.apache.shiro.web.WebUtils;
@@ -35,7 +32,6 @@
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import java.io.Serializable;
-import java.net.InetAddress;
 
 
 /**
@@ -50,18 +46,14 @@
 
     private static final Logger log = LoggerFactory.getLogger(DefaultWebSessionManager.class);
 
-    /**
-     * Property specifying if, after a session object is acquired from the request, if that session should be
-     * validated to ensure the starting origin of the session is the same as the incoming request.
-     */
-    private boolean validateRequestOrigin = false; //default
-
-    protected CookieAttribute<Serializable> sessionIdCookieAttribute = null;
-    protected RequestParamAttribute<Serializable> sessionIdRequestParamAttribute = null;
+    private CookieAttribute<Serializable> sessionIdCookieAttribute = null;
+    private RequestParamAttribute<Serializable> sessionIdRequestParamAttribute = null;
 
     public DefaultWebSessionManager() {
-        ensureCookieSessionIdStore();
-        ensureRequestParamSessionIdStore();
+        this.sessionIdCookieAttribute = new CookieAttribute<Serializable>(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
+        this.sessionIdCookieAttribute.setCheckRequestParams(false);
+        this.sessionIdRequestParamAttribute =
+                new RequestParamAttribute<Serializable>(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
     }
 
     public CookieAttribute<Serializable> getSessionIdCookieAttribute() {
@@ -80,47 +72,6 @@
         this.sessionIdRequestParamAttribute = sessionIdRequestParamAttribute;
     }
 
-    /**
-     * If set to <tt>true</tt>, this implementation will ensure that any
-     * <tt>HttpRequest</tt> attempting
-     * to join a session (i.e. via {@link #getSession getSession} must have the same
-     * IP Address of the <tt>HttpRequest</tt> that started the session.
-     * <p/>
-     * <p> If set to <tt>false</tt>, any <tt>HttpRequest</tt> with a reference to a valid
-     * session id may acquire that <tt>Session</tt>.
-     * <p/>
-     * <p>Although convenient, this should only be enabled in environments where the
-     * system can <em>guarantee</em> that each IP address represents one and only one
-     * machine accessing the system.
-     * <p/>
-     * <p>Public websites are not good candidates for enabling this
-     * feature since many browser clients often sit behind NAT routers (in
-     * which case many machines are viewed to come from the same IP, thereby making this
-     * validation check useless).  Also, some internet service providers (e.g. AOL) may change a
-     * client's IP in mid-session, making subsequent requests appear to come from a different
-     * location.  Again, this feature should only be enabled where IP Addresses can be guaranteed a
-     * 1-to-1 relationship with a user's session.
-     * <p/>
-     * <p>For the reasons specified above, this property is <tt>false</tt> by default.
-     *
-     * @return true if this factory will verify each HttpRequest joining a session
-     */
-    public boolean isValidateRequestOrigin() {
-        return validateRequestOrigin;
-    }
-
-    /**
-     * Sets whether or not a request's origin will be validated when accessing a session.  See
-     * the {@link #isValidateRequestOrigin} JavaDoc for an in-depth explanation of this property.
-     *
-     * @param validateRequestOrigin whether or not to validate the request's origin when accessing
-     *                              a session.
-     * @see #isValidateRequestOrigin
-     */
-    public void setValidateRequestOrigin(boolean validateRequestOrigin) {
-        this.validateRequestOrigin = validateRequestOrigin;
-    }
-
     public void setSessionIdCookieName(String name) {
         getSessionIdCookieAttribute().setName(name);
     }
@@ -149,67 +100,12 @@
         getSessionIdCookieAttribute().setComment(comment);
     }
 
-    protected void ensureCookieSessionIdStore() {
-        CookieAttribute<Serializable> cookieStore = getSessionIdCookieAttribute();
-        if (cookieStore == null) {
-            cookieStore = new CookieAttribute<Serializable>(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
-            cookieStore.setCheckRequestParams(false);
-            setSessionIdCookieAttribute(cookieStore);
-        }
-    }
-
-    protected void ensureRequestParamSessionIdStore() {
-        RequestParamAttribute<Serializable> reqParamStore = getSessionIdRequestParamAttribute();
-        if (reqParamStore == null) {
-            reqParamStore = new RequestParamAttribute<Serializable>(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
-            setSessionIdRequestParamAttribute(reqParamStore);
-        }
-    }
-
-    protected void validateSessionOrigin(ServletRequest request, Session session)
-            throws HostUnauthorizedException {
-        InetAddress requestIp = WebUtils.getInetAddress(request);
-        InetAddress originIp = session.getHostAddress();
-        Serializable sessionId = session.getId();
-
-        if (originIp == null) {
-            if (requestIp != null) {
-                String msg = "No IP Address was specified when creating session with id [" +
-                        sessionId + "].  Attempting to access session from " +
-                        "IP [" + requestIp + "].  Origin IP and request IP must match.";
-                throw new HostUnauthorizedException(msg);
-            }
-        } else {
-            if (requestIp != null) {
-                if (!requestIp.equals(originIp)) {
-                    String msg = "Session with id [" + sessionId + "] originated from [" +
-                            originIp + "], but the current HttpServletRequest originated " +
-                            "from [" + requestIp + "].  Disallowing session access: " +
-                            "session origin and request origin must match to allow access.";
-                    throw new HostUnauthorizedException(msg);
-                }
-
-            } else {
-                String msg = "No IP Address associated with the current HttpServletRequest.  " +
-                        "Session with id [" + sessionId + "] originated from " +
-                        "[" + originIp + "].  Request IP must match the session's origin " +
-                        "IP in order to gain access to that session.";
-                throw new HostUnauthorizedException(msg);
-            }
-        }
-    }
-
     protected void storeSessionId(Serializable currentId, ServletRequest request, ServletResponse response) {
         if (currentId == null) {
             String msg = "sessionId cannot be null when persisting for subsequent requests.";
             throw new IllegalArgumentException(msg);
         }
-        //ensure that the id has been set in the idStore, or if it already has, that it is not different than the
-        //'real' session value:
-        Serializable existingId = getReferencedSessionId(request, response);
-        if (existingId == null || !currentId.equals(existingId)) {
-            getSessionIdCookieAttribute().storeValue(currentId, request, response);
-        }
+        getSessionIdCookieAttribute().storeValue(currentId, request, response);
     }
 
     private void markSessionIdValid(Serializable sessionId, ServletRequest request) {
@@ -220,7 +116,6 @@
         getSessionIdCookieAttribute().removeValue(request, response);
     }
 
-
     protected Serializable getReferencedSessionId(ServletRequest request, ServletResponse response) {
         WebAttribute<Serializable> cookieSessionIdAttribute = getSessionIdCookieAttribute();
         Serializable id = cookieSessionIdAttribute.retrieveValue(request, response);
@@ -249,82 +144,14 @@
     protected void onStart(Session session) {
         ServletRequest request = WebUtils.getRequiredServletRequest();
         ServletResponse response = WebUtils.getRequiredServletResponse();
-        onStart(session, request, response);
-    }
-
-    protected void onStart(Session session, ServletRequest request, ServletResponse response) {
         Serializable sessionId = session.getId();
         storeSessionId(sessionId, request, response);
-        onSessionStart(request);
-    }
-
-    protected void onSessionStart(ServletRequest request) {
         request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
         request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
     }
 
-    @Override
-    protected Session retrieveSession(Serializable sessionId) throws InvalidSessionException, AuthorizationException {
-        if (sessionId == null) {
-            ServletRequest request = WebUtils.getRequiredServletRequest();
-            ServletResponse response = WebUtils.getRequiredServletResponse();
-            return getSession(request, response);
-        }
-        return retrieveSessionFromDataSource(sessionId);
-    }
-
-    /**
-     * Returns the Session associated with the specified request if it is valid or <tt>null</tt> if a Session doesn't
-     * exist or it was invalid.
-     *
-     * @param request  incoming servlet request
-     * @param response outgoing servlet response
-     * @return the Session associated with the incoming request or <tt>null</tt> if one does not exist.
-     * @throws org.apache.shiro.authz.AuthorizationException
-     *          if the caller is not authorized to access the session associated with the request.
-     */
-    public Session getSession(ServletRequest request, ServletResponse response)
-            throws InvalidSessionException, AuthorizationException {
-
-        Session session = null;
-        Serializable sessionId = getReferencedSessionId(request, response);
-
-        if (sessionId != null) {
-            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
-            try {
-                session = retrieveSessionFromDataSource(sessionId);
-                markSessionIdValid(sessionId, request);
-            } catch (InvalidSessionException ise) {
-                if (log.isTraceEnabled()) {
-                    log.trace("Request Session with id [" + ise.getSessionId() + "] is invalid, message: [" +
-                            ise.getMessage() + "].  Removing any associated session cookie...");
-                }
-                removeSessionIdCookie(request, response);
-                //give subclass a chance to do something additional if necessary.  Otherwise returning null is just fine:
-                session = handleInvalidSession(request, response, ise);
-            }
-            if (isValidateRequestOrigin()) {
-                if (log.isDebugEnabled()) {
-                    log.debug("Validating request origin against session origin");
-                }
-                validateSessionOrigin(request, session);
-            }
-        } else {
-            if (log.isTraceEnabled()) {
-                log.trace("A valid Shiro session id was not associated with the current request.");
-            }
-        }
-
-        return session;
-    }
-
-    protected Session handleInvalidSession(ServletRequest request,
-                                           ServletResponse response,
-                                           InvalidSessionException ise) {
-        if (log.isTraceEnabled()) {
-            log.trace("Sesssion associated with the current request is nonexistent or invalid.  Returning null.");
-        }
-        return null;
+    public Serializable getSessionId(ServletRequest request, ServletResponse response) {
+        return getReferencedSessionId(request, response);
     }
 
     protected void onStop(Session session) {

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java Thu Jul 23 23:01:19 2009
@@ -80,6 +80,11 @@
         return session;
     }
 
+    public Serializable getSessionId(ServletRequest request, ServletResponse response) {
+        HttpSession httpSession = ((HttpServletRequest) request).getSession(false);
+        return httpSession != null ? httpSession.getId() : null;
+    }
+
     protected Session createSession(Map initData) throws AuthorizationException {
 
         ServletRequest request = WebUtils.getRequiredServletRequest();

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java Thu Jul 23 23:01:19 2009
@@ -18,17 +18,16 @@
  */
 package org.apache.shiro.web.session;
 
+import org.apache.shiro.session.mgt.SessionManager;
+
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
-
-import org.apache.shiro.session.Session;
-import org.apache.shiro.session.mgt.SessionManager;
+import java.io.Serializable;
 
 
 /**
- * A <code>WebSessionManager</code> is a <code>SessionManager</code> that has the ability to obtain
- * {@link Session Session}s based on a {@link ServletRequest ServletRequest}/{@link ServletResponse ServletResponse}
- * pair.
+ * A {@code WebSessionManager} is a {@code SessionManager} that has the ability to obtain session ids based on a
+ * {@link ServletRequest ServletRequest}/{@link ServletResponse ServletResponse} pair.
  *
  * @author Les Hazlewood
  * @since 0.9
@@ -36,14 +35,14 @@
 public interface WebSessionManager extends SessionManager {
 
     /**
-     * Returns the current {@link Session Session} associated with the specified request pair, or
-     * <code>null</code> if there is no session associated with the request.
-     * 
-     * @param request the incoming <code>ServletRequest</code>
-     * @param response the outgoing <code>ServletResponse</code>
-     * @return the current {@link Session Session} associated with the specified request pair, or
-     * <code>null</code> if there is no session associated with the request. 
+     * Returns the session id associated with the specified request pair or {@code null} if there is no session
+     * associated with the request.
+     *
+     * @param request  the incoming {@code ServletRequest}
+     * @param response the outgoing {@code ServletResponse}
+     * @return the current session id associated with the specified request pair, or {@code null} if there is no
+     *         session associated with the request.
+     * @since 1.0
      */
-    Session getSession(ServletRequest request, ServletResponse response);
-
+    Serializable getSessionId(ServletRequest request, ServletResponse response);
 }

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DefaultWebSecurityManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DefaultWebSecurityManagerTest.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DefaultWebSecurityManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/DefaultWebSecurityManagerTest.java Thu Jul 23 23:01:19 2009
@@ -21,16 +21,20 @@
 import org.apache.shiro.session.Session;
 import org.apache.shiro.subject.Subject;
 import org.apache.shiro.util.ThreadContext;
+import org.apache.shiro.web.servlet.ShiroHttpSession;
 import static org.easymock.EasyMock.*;
 import org.junit.After;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.*;
 import org.junit.Before;
 import org.junit.Test;
 
+import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.Serializable;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.HashMap;
 
 /**
  * @author Les Hazlewood
@@ -94,4 +98,86 @@
         assertFalse(origId.equals(session.getId())); //new ID would have been generated
     }
 
+    public static InetAddress getLocalHost() {
+        try {
+            return InetAddress.getLocalHost();
+        } catch (UnknownHostException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Test
+    public void testGetSubjectByRequestResponsePair() {
+        shiroSessionModeInit();
+
+        HttpServletRequest mockRequest = createNiceMock(HttpServletRequest.class);
+        WebUtils.bind(mockRequest);
+        HttpServletResponse mockResponse = createNiceMock(HttpServletResponse.class);
+        WebUtils.bind(mockResponse);
+
+        expect(mockRequest.getCookies()).andReturn(null);
+        //expect(mockRequest.getContextPath()).andReturn("/");
+
+        replay(mockRequest);
+        replay(mockResponse);
+
+        Subject subject = sm.getSubject(new HashMap());
+
+        verify(mockRequest);
+        verify(mockResponse);
+
+        assertNotNull(subject);
+        assertTrue(subject.getPrincipals() == null || subject.getPrincipals().isEmpty());
+        assertTrue(subject.getSession(false) == null);
+        assertFalse(subject.isAuthenticated());
+    }
+
+    @Test
+    public void testGetSubjectByRequestSessionId() {
+
+        shiroSessionModeInit();
+
+        HttpServletRequest mockRequest = createNiceMock(HttpServletRequest.class);
+        WebUtils.bind(mockRequest);
+        HttpServletResponse mockResponse = createNiceMock(HttpServletResponse.class);
+        WebUtils.bind(mockResponse);
+
+        //expect(mockRequest.getCookies()).andReturn(null);
+        //expect(mockRequest.getContextPath()).andReturn("/");
+
+        replay(mockRequest);
+        replay(mockResponse);
+
+        Subject subject = sm.getSubject(new HashMap());
+
+        Session session = subject.getSession();
+        Serializable sessionId = session.getId();
+
+        assertNotNull(sessionId);
+
+        verify(mockRequest);
+        verify(mockResponse);
+
+        mockRequest = createNiceMock(HttpServletRequest.class);
+        WebUtils.bind(mockRequest);
+        mockResponse = createNiceMock(HttpServletResponse.class);
+        WebUtils.bind(mockResponse);
+        //now simulate the cookie going with the request and the Subject should be acquired based on that:
+        Cookie[] cookies = new Cookie[]{new Cookie(ShiroHttpSession.DEFAULT_SESSION_ID_NAME, sessionId.toString())};
+        expect(mockRequest.getCookies()).andReturn(cookies).anyTimes();
+        expect(mockRequest.getParameter(isA(String.class))).andReturn(null).anyTimes();
+
+        replay(mockRequest);
+        replay(mockResponse);
+
+        subject = sm.getSubject(new HashMap());
+
+        session = subject.getSession(false);
+        assertNotNull(session);
+        assertEquals(sessionId, session.getId());
+
+        verify(mockRequest);
+        verify(mockResponse);
+    }
+
 }

Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java?rev=797256&r1=797255&r2=797256&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/ShiroFilterTest.java Thu Jul 23 23:01:19 2009
@@ -18,22 +18,20 @@
  */
 package org.apache.shiro.web.servlet;
 
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletContext;
-
 import static org.easymock.EasyMock.*;
 import org.junit.Test;
 
-import org.apache.shiro.web.servlet.ShiroFilter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
 
 
 /**
  * @author Les Hazlewood
  * @since 0.9
  */
-public class ShiroFilterTest
-{
+public class ShiroFilterTest {
 
+    @SuppressWarnings({"FieldCanBeLocal"})
     private ShiroFilter filter;
     private FilterConfig mockFilterConfig;
     private ServletContext mockServletContext;

Added: incubator/shiro/trunk/web/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/resources/log4j.properties?rev=797256&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/resources/log4j.properties (added)
+++ incubator/shiro/trunk/web/src/test/resources/log4j.properties Thu Jul 23 23:01:19 2009
@@ -0,0 +1,38 @@
+#
+# 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.
+#
+log4j.rootLogger=TRACE, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
+
+# Pattern to output: date priority [category] - message
+log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
+log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
+
+# Spring logging level is WARN
+log4j.logger.org.springframework=WARN
+
+# General Apache libraries is WARN
+log4j.logger.org.apache=WARN
+
+log4j.logger.net.sf.ehcache=WARN
+
+log4j.logger.org.apache.shiro=TRACE
+log4j.logger.org.apache.shiro.util.ThreadContext=WARN
\ No newline at end of file