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/06/05 02:21:41 UTC

svn commit: r781878 - in /incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web: DefaultWebSecurityManager.java WebRememberMeManager.java attr/CookieAttribute.java session/DefaultWebSessionManager.java

Author: lhazlewood
Date: Fri Jun  5 00:21:40 2009
New Revision: 781878

URL: http://svn.apache.org/viewvc?rev=781878&view=rev
Log:
KI-80: Added passthrough configuration attributes for Cookie domain, comment and version

Modified:
    incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/DefaultWebSecurityManager.java
    incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/WebRememberMeManager.java
    incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/attr/CookieAttribute.java
    incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/session/DefaultWebSessionManager.java

Modified: incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/DefaultWebSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/DefaultWebSecurityManager.java?rev=781878&r1=781877&r2=781878&view=diff
==============================================================================
--- incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/DefaultWebSecurityManager.java (original)
+++ incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/DefaultWebSecurityManager.java Fri Jun  5 00:21:40 2009
@@ -23,6 +23,7 @@
 import org.apache.ki.session.mgt.SessionManager;
 import org.apache.ki.subject.PrincipalCollection;
 import org.apache.ki.util.LifecycleUtils;
+import org.apache.ki.web.attr.CookieAttribute;
 import org.apache.ki.web.servlet.KiHttpServletRequest;
 import org.apache.ki.web.session.DefaultWebSessionManager;
 import org.apache.ki.web.session.ServletContainerSessionManager;
@@ -31,6 +32,7 @@
 import org.slf4j.LoggerFactory;
 
 import javax.servlet.ServletRequest;
+import java.io.Serializable;
 import java.util.Collection;
 
 
@@ -50,10 +52,14 @@
     public static final String HTTP_SESSION_MODE = "http";
     public static final String KI_SESSION_MODE = "ki";
 
-    /** The key that is used to store subject principals in the session. */
+    /**
+     * The key that is used to store subject principals in the session.
+     */
     public static final String PRINCIPALS_SESSION_KEY = DefaultWebSecurityManager.class.getName() + "_PRINCIPALS_SESSION_KEY";
 
-    /** The key that is used to store whether or not the user is authenticated in the session. */
+    /**
+     * The key that is used to store whether or not the user is authenticated in the session.
+     */
     public static final String AUTHENTICATED_SESSION_KEY = DefaultWebSecurityManager.class.getName() + "_AUTHENTICATED_SESSION_KEY";
 
     private String sessionMode = HTTP_SESSION_MODE; //default
@@ -82,6 +88,33 @@
         setSubjectFactory(new WebSubjectFactory(this, sessionManager));
     }
 
+    //TODO - yuck - create an interface
+    protected WebRememberMeManager getRememberMeManagerForCookieAttributes() {
+        if (!(getRememberMeManager() instanceof WebRememberMeManager)) {
+            String msg = "Currently the " + getClass().getName() + " implementation only allows setting " +
+                    "rememberMe cookie attributes directly if the underlying RememberMeManager implementation " +
+                    "is an " + WebRememberMeManager.class.getName() + " instance.";
+            throw new IllegalStateException(msg);
+        }
+        return (WebRememberMeManager) getRememberMeManager();
+    }
+
+    protected CookieAttribute<String> getRememberMeCookieAttribute() {
+        return (CookieAttribute<String>) getRememberMeManagerForCookieAttributes().getIdentityAttribute();
+    }
+
+    public void setRememberMeCookieAttribute(CookieAttribute<String> cookieAttribute) {
+        getRememberMeManagerForCookieAttributes().setIdentityAttribute(cookieAttribute);
+    }
+
+    public void setRememberMeCookieName(String name) {
+        getRememberMeCookieAttribute().setName(name);
+    }
+
+    public void setRememberMeCookieDomain(String domain) {
+        getRememberMeCookieAttribute().setDomain(domain);
+    }
+
     /**
      * Sets the path used to store the remember me cookie.  This determines which paths
      * are able to view the remember me cookie.
@@ -89,19 +122,31 @@
      * @param rememberMeCookiePath the path to use for the remember me cookie.
      */
     public void setRememberMeCookiePath(String rememberMeCookiePath) {
-        ((WebRememberMeManager) getRememberMeManager()).setCookiePath(rememberMeCookiePath);
+        getRememberMeCookieAttribute().setPath(rememberMeCookiePath);
     }
 
     /**
      * Sets the maximum age allowed for the remember me cookie.  This basically sets how long
      * a user will be remembered by the "remember me" feature.  Used when calling
      * {@link javax.servlet.http.Cookie#setMaxAge(int) maxAge}.  Please see that JavaDoc for the semantics on the
-     * repercussions of negative, zero, and positive values for the maxAge.
+     * repercussions of negative, zero, and positive values for the maxAge.                           i
      *
      * @param rememberMeMaxAge the maximum age for the remember me cookie.
      */
     public void setRememberMeCookieMaxAge(Integer rememberMeMaxAge) {
-        ((WebRememberMeManager) getRememberMeManager()).setCookieMaxAge(rememberMeMaxAge);
+        getRememberMeCookieAttribute().setMaxAge(rememberMeMaxAge);
+    }
+
+    public void setRememberMeCookieVersion(int version) {
+        getRememberMeCookieAttribute().setVersion(version);
+    }
+
+    public void setRememberMeCookieSecure(boolean secure) {
+        getRememberMeCookieAttribute().setSecure(secure);
+    }
+
+    public void setRememberMeCookieComment(String comment) {
+        getRememberMeCookieAttribute().setComment(comment);
     }
 
     private DefaultWebSessionManager getSessionManagerForCookieAttributes() {
@@ -116,20 +161,40 @@
         return (DefaultWebSessionManager) sessionManager;
     }
 
+    protected CookieAttribute<Serializable> getSessionIdCookieAttribute() {
+        return getSessionManagerForCookieAttributes().getSessionIdCookieAttribute();
+    }
+
+    public void setSessionIdCookieAttribute(CookieAttribute<Serializable> cookieAttribute) {
+        getSessionManagerForCookieAttributes().setSessionIdCookieAttribute(cookieAttribute);
+    }
+
     public void setSessionIdCookieName(String name) {
-        getSessionManagerForCookieAttributes().setSessionIdCookieName(name);
+        getSessionIdCookieAttribute().setName(name);
+    }
+
+    public void setSessionIdCookieDomain(String domain) {
+        getSessionIdCookieAttribute().setDomain(domain);
     }
 
     public void setSessionIdCookiePath(String path) {
-        getSessionManagerForCookieAttributes().setSessionIdCookiePath(path);
+        getSessionIdCookieAttribute().setPath(path);
     }
 
     public void setSessionIdCookieMaxAge(int maxAge) {
-        getSessionManagerForCookieAttributes().setSessionIdCookieMaxAge(maxAge);
+        getSessionIdCookieAttribute().setMaxAge(maxAge);
+    }
+
+    public void setSessionIdCookieVersion(int version) {
+        getSessionIdCookieAttribute().setVersion(version);
     }
 
     public void setSessionIdCookieSecure(boolean secure) {
-        getSessionManagerForCookieAttributes().setSessionIdCookieSecure(secure);
+        getSessionIdCookieAttribute().setSecure(secure);
+    }
+
+    public void setSessionIdCookieComment(String comment) {
+        getSessionIdCookieAttribute().setComment(comment);
     }
 
     public String getSessionMode() {

Modified: incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/WebRememberMeManager.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/WebRememberMeManager.java?rev=781878&r1=781877&r2=781878&view=diff
==============================================================================
--- incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/WebRememberMeManager.java (original)
+++ incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/WebRememberMeManager.java Fri Jun  5 00:21:40 2009
@@ -18,40 +18,39 @@
  */
 package org.apache.ki.web;
 
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import org.apache.ki.codec.Base64;
 import org.apache.ki.mgt.AbstractRememberMeManager;
 import org.apache.ki.web.attr.CookieAttribute;
 import org.apache.ki.web.attr.WebAttribute;
 import org.apache.ki.web.servlet.KiHttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 
 
 /**
  * Remembers a Subject's identity by using a {@link WebAttribute WebAttribute} instance to retain
  * the identity value between web requests.
- *
- * <p>This class's default <code>WebAttribute</code> instance is a {@link org.apache.ki.web.attr.CookieAttribute CookieAttribute}, storing
+ * <p/>
+ * This class's default <code>WebAttribute</code> instance is a {@link org.apache.ki.web.attr.CookieAttribute CookieAttribute}, storing
  * the Subject's {@link org.apache.ki.subject.Subject#getPrincipals principals} in a <code>Cookie</code>.  Note that
  * because this class subclasses the <code>AbstractRememberMeManager</code> which already provides serialization and
- * encryption logic, this class utilizes both for added security before setting the cookie value.</p>
- *
- * <p>This class also contains &quot;passthrough&quot; JavaBeans-compatible getters/setters for the underlying
- * <code>CookieAttribute</code>'s properties to make configuration easier.</p>
- *
- * <p>Note however as a basic sanity check, these passthrough methods will first assert that the underlying
+ * encryption logic, this class utilizes both for added security before setting the cookie value.
+ * <p/>
+ * This class also contains &quot;passthrough&quot; JavaBeans-compatible getters/setters for the underlying
+ * <code>CookieAttribute</code>'s properties to make configuration easier.
+ * <p/>
+ * Note however as a basic sanity check, these passthrough methods will first assert that the underlying
  * {@link #getIdentityAttribute identityAttribute} is actually a {@link CookieAttribute CookieAttribute}.  If it
  * is not, an {@link IllegalStateException} will be thrown.  Because the default instance of this class <em>is</em>
  * already <code>CookieAttribute</code>, you would only ever experience the exception if you explicitly
  * override the internal instance with a different type and accidentally call one of these JavaBeans passthrough
- * methods.</p>
- *
- * <p>Just be aware of this if you manually override the {@link #getIdentityAttribute identityAttribute} property
- * to be an instance of something <em>other</em> than a <code>CookieAttribute</code>.</p>
+ * methods.
+ * <p/>
+ * Just be aware of this if you manually override the {@link #getIdentityAttribute identityAttribute} property
+ * to be an instance of something <em>other</em> than a <code>CookieAttribute</code>.
  *
  * @author Les Hazlewood
  * @author Luis Arias
@@ -88,6 +87,11 @@
         this.identityAttribute = identityAttribute;
     }
 
+    protected CookieAttribute getCookieAttribute() {
+        assertCookieAttribute();
+        return (CookieAttribute) getIdentityAttribute();
+    }
+
     protected void assertCookieAttribute() {
         if (!(this.identityAttribute instanceof CookieAttribute)) {
             String msg = "Attempting to access a Cookie property, but the underlying " +
@@ -100,102 +104,118 @@
 
     /**
      * Passthrough JavaBeans property that will get the underyling rememberMe cookie's name.
-     *
-     * <p>The default value is {@link #DEFAULT_REMEMBER_ME_COOKIE_NAME}</p>
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * The default value is {@link #DEFAULT_REMEMBER_ME_COOKIE_NAME}
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @return the underlying rememberMe cookie's name
      */
     public String getCookieName() {
-        assertCookieAttribute();
-        return ((CookieAttribute) this.identityAttribute).getName();
+        return getCookieAttribute().getName();
     }
 
     /**
      * Passthrough JavaBeans property that will set the underyling rememberMe cookie's name.
-     *
-     * <p>The default value is {@link #DEFAULT_REMEMBER_ME_COOKIE_NAME}</p>
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * The default value is {@link #DEFAULT_REMEMBER_ME_COOKIE_NAME}
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @param name the name to assign to the underlying rememberMe cookie
      */
     public void setCookieName(String name) {
-        assertCookieAttribute();
-        ((CookieAttribute) this.identityAttribute).setName(name);
+        getCookieAttribute().setName(name);
+    }
+
+    public String getCookieDomain() {
+        return getCookieAttribute().getDomain();
+    }
+
+    public void setCookieDomain(String domain) {
+        getCookieAttribute().setDomain(domain);
     }
 
     /**
      * Passthrough JavaBeans property that will get the underyling rememberMe cookie's path.
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @return the underlying rememberMe cookie's path
      */
     public String getCookiePath() {
-        assertCookieAttribute();
-        return ((CookieAttribute) this.identityAttribute).getPath();
+        return getCookieAttribute().getPath();
     }
 
     /**
      * Passthrough JavaBeans property that will set the underyling rememberMe cookie's path.
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @param path the path to assign to the underlying rememberMe cookie
      */
     public void setCookiePath(String path) {
-        assertCookieAttribute();
-        ((CookieAttribute) this.identityAttribute).setPath(path);
+        getCookieAttribute().setPath(path);
     }
 
     /**
      * Passthrough JavaBeans property that will get the underyling rememberMe cookie's max age.
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @return the underlying rememberMe cookie's max age.
      */
     public int getCookieMaxAge() {
-        assertCookieAttribute();
-        return ((CookieAttribute) this.identityAttribute).getMaxAge();
+        return getCookieAttribute().getMaxAge();
     }
 
     /**
      * Passthrough JavaBeans property that will get the underyling rememberMe cookie's max age.
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @param maxAge the max age to assign to the underlying rememberMe cookie
      */
     public void setCookieMaxAge(int maxAge) {
-        assertCookieAttribute();
-        ((CookieAttribute) this.identityAttribute).setMaxAge(maxAge);
+        getCookieAttribute().setMaxAge(maxAge);
+    }
+
+    public int getCookieVersion() {
+        return getCookieAttribute().getVersion();
+    }
+
+    public void setCookieVersion(int version) {
+        getCookieAttribute().setVersion(version);
     }
 
     /**
      * Passthrough JavaBeans property that will get the underyling rememberMe cookie's 'secure' status.
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @return the underlying rememberMe cookie's 'secure' flag
      */
     public boolean isCookieSecure() {
-        assertCookieAttribute();
-        return ((CookieAttribute) this.identityAttribute).isSecure();
+        return getCookieAttribute().isSecure();
     }
 
     /**
      * Passthrough JavaBeans property that will set the underyling rememberMe cookie's 'secure' status.
-     *
-     * <p>This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.</p>
+     * <p/>
+     * This method performs a quick <code>CookieAttribute</code> sanity check as described in the class-level JavaDoc.
      *
      * @param secure the 'secure' flag to assign to the underlying rememberMe cookie.
      */
     public void setCookieSecure(boolean secure) {
-        assertCookieAttribute();
-        ((CookieAttribute) this.identityAttribute).setSecure(secure);
+        getCookieAttribute().setSecure(secure);
+    }
+
+    public String getCookieComment() {
+        return getCookieAttribute().getComment();
+    }
+
+    public void setCookieComment(String comment) {
+        getCookieAttribute().setComment(comment);
     }
 
     protected void rememberSerializedIdentity(byte[] serialized) {
@@ -208,14 +228,15 @@
 
     protected boolean isIdentityRemoved() {
         ServletRequest request = WebUtils.getServletRequest();
-        if ( request != null ) {
-            Boolean removed = (Boolean)request.getAttribute(KiHttpServletRequest.IDENTITY_REMOVED_KEY);
+        if (request != null) {
+            Boolean removed = (Boolean) request.getAttribute(KiHttpServletRequest.IDENTITY_REMOVED_KEY);
             return removed != null && removed;
         }
         return false;
     }
+
     protected byte[] getSerializedRememberedIdentity() {
-        if ( isIdentityRemoved() ) {
+        if (isIdentityRemoved()) {
             return null;
         }
 
@@ -240,8 +261,9 @@
 
     /**
      * Sometimes a user agent will send the rememberMe cookie value without padding,
-     * most likely because {@code =} is a separator in the cookie header.  Contributed
-     * by Luis Arias.
+     * most likely because {@code =} is a separator in the cookie header.
+     * <p/>
+     * Contributed by Luis Arias.  Thanks Luis!
      *
      * @param base64 the base64 encoded String that may need to be padded
      * @return the base64 String padded if necessary.

Modified: incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/attr/CookieAttribute.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/attr/CookieAttribute.java?rev=781878&r1=781877&r2=781878&view=diff
==============================================================================
--- incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/attr/CookieAttribute.java (original)
+++ incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/attr/CookieAttribute.java Fri Jun  5 00:21:40 2009
@@ -18,18 +18,17 @@
  */
 package org.apache.ki.web.attr;
 
-import java.beans.PropertyEditor;
+import org.apache.ki.util.StringUtils;
+import static org.apache.ki.web.WebUtils.toHttp;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.apache.ki.util.StringUtils;
-import static org.apache.ki.web.WebUtils.toHttp;
+import java.beans.PropertyEditor;
 
 /**
  * A <tt>CookieAttribute</tt> stores an object as a {@link Cookie} for access on later requests.
@@ -71,14 +70,23 @@
      * <code>-1</code>, indicating the cookie should expire when the browser closes.
      */
     public static final int DEFAULT_MAX_AGE = -1;
+
+    /**
+     * <code>-1</code> indicating that no version property should be set on the cookie.
+     */
+    public static final int DEFAULT_VERSION = -1;
+
     /**
      * Default value is <code>false</code>.
      */
     public static final boolean DEFAULT_SECURE = false;
 
-    private String path = DEFAULT_PATH;
+    private String comment = null;
+    private String domain = null;
     private int maxAge = DEFAULT_MAX_AGE;
+    private String path = DEFAULT_PATH;
     private boolean secure = DEFAULT_SECURE;
+    private int version = DEFAULT_VERSION;
 
     public CookieAttribute() {
     }
@@ -97,9 +105,9 @@
     /**
      * Constructs a <tt>CookieAttribute</tt> using a {@link Cookie Cookie} with the specified
      * {@link Cookie#getName() name} and {@link Cookie#getPath() path}.
-     *
+     * <p/>
      * <p>A <tt>null</tt> <tt>path</tt> value means the request context's path will be used by default.
-     *
+     * <p/>
      * <p>The Cookie's {@link Cookie#getMaxAge() maxAge} will be <tt>-1</tt>, indicating the Cookie will persist until
      * browser shutdown.
      *
@@ -114,7 +122,7 @@
     /**
      * Constructs a <tt>CookieAttribute</tt> using a {@link Cookie Cookie} with the specified
      * {@link Cookie#getName() name} and {@link Cookie#getMaxAge() maxAge}.
-     *
+     * <p/>
      * <p>The Cookie's {@link javax.servlet.http.Cookie#getPath() path} will be the <tt>Request</tt>'s
      * {@link javax.servlet.http.HttpServletRequest#getContextPath() context path}.
      *
@@ -158,11 +166,27 @@
         setMaxAge(maxAge);
     }
 
+    public String getComment() {
+        return comment;
+    }
+
+    public void setComment(String comment) {
+        this.comment = comment;
+    }
+
+    public String getDomain() {
+        return domain;
+    }
+
+    public void setDomain(String domain) {
+        this.domain = domain;
+    }
+
     /**
      * Returns the Cookie's {@link Cookie#getPath() path} setting.  If <tt>null</tt>, the <tt>request</tt>'s
      * {@link javax.servlet.http.HttpServletRequest#getContextPath() context path} will be used.
-     *
-     * <p>The default is <code>null</code>.</p>
+     * <p/>
+     * The default is <code>null</code>.
      *
      * @return the Cookie's path, or <tt>null</tt> if the request's context path should be used as the path when the
      *         cookie is created.
@@ -173,31 +197,9 @@
 
 
     /**
-     * Returns the Cookie's calculated path setting.  If {@link Cookie#getPath() path} <tt>null</tt>, then the
-     * <tt>request</tt>'s {@link javax.servlet.http.HttpServletRequest#getContextPath() context path}
-     * will be returned. If getContextPath() is the empty string or null then the ROOT_PATH constant is returned.
-     * <p/>
-     * <p>The default is <code>null</code>.</p>
-     *
-     * @return the path to be used as the path when the cookie is created or removed.
-     */
-    public String calculatePath(HttpServletRequest request) {
-        String calculatePath = getPath() != null ? getPath() : request.getContextPath();
-
-        //fix for http://issues.apache.org/jira/browse/JSEC-34:
-        calculatePath = StringUtils.clean(calculatePath);
-        if (calculatePath == null) {
-            calculatePath = ROOT_PATH;
-        }
-        log.trace ("calculatePath: returning=" + calculatePath);
-        return calculatePath;
-    }
-
-
-    /**
      * Sets the Cookie's {@link Cookie#getPath() path} setting.  If the argument is <tt>null</tt>, the <tt>request</tt>'s
      * {@link javax.servlet.http.HttpServletRequest#getContextPath() context path} will be used.
-     *
+     * <p/>
      * <p>The default is <code>null</code>.</p>
      *
      * @param path the Cookie's path, or <tt>null</tt> if the request's context path should be used as the path when the
@@ -210,7 +212,7 @@
     /**
      * Returns the Cookie's {@link Cookie#setMaxAge(int) maxAge} setting.  Please see that JavaDoc for the semantics on
      * the repercussions of negative, zero, and positive values for the maxAge.
-     *
+     * <p/>
      * <p>The default value is <code>-1</code>, meaning the cookie will expire when the browser is closed.</p>
      *
      * @return the Cookie's {@link Cookie#setMaxAge(int) maxAge}
@@ -222,7 +224,7 @@
     /**
      * Sets the Cookie's {@link Cookie#setMaxAge(int) maxAge} setting.  Please see that JavaDoc for the semantics on
      * the repercussions of negative, zero, and positive values for the maxAge.
-     *
+     * <p/>
      * <p>The default value is <code>-1</code>, meaning the cookie will expire when the browser is closed.</p>
      *
      * @param maxAge the Cookie's {@link Cookie#setMaxAge(int) maxAge}
@@ -239,6 +241,14 @@
         this.secure = secure;
     }
 
+    public int getVersion() {
+        return version;
+    }
+
+    public void setVersion(int version) {
+        this.version = version;
+    }
+
     /**
      * Returns the cookie with the given name from the request or <tt>null</tt> if no cookie
      * with that name could be found.
@@ -280,12 +290,36 @@
         return value;
     }
 
+    /**
+     * Returns the Cookie's calculated path setting.  If {@link Cookie#getPath() path} <tt>null</tt>, then the
+     * <tt>request</tt>'s {@link javax.servlet.http.HttpServletRequest#getContextPath() context path}
+     * will be returned. If getContextPath() is the empty string or null then the ROOT_PATH constant is returned.
+     * <p/>
+     * <p>The default is <code>null</code>.</p>
+     *
+     * @return the path to be used as the path when the cookie is created or removed.
+     */
+    public String calculatePath(HttpServletRequest request) {
+        String calculatePath = getPath() != null ? getPath() : request.getContextPath();
+
+        //fix for http://issues.apache.org/jira/browse/JSEC-34:
+        calculatePath = StringUtils.clean(calculatePath);
+        if (calculatePath == null) {
+            calculatePath = ROOT_PATH;
+        }
+        log.trace("calculatePath: returning=" + calculatePath);
+        return calculatePath;
+    }
+
     public void onStoreValue(T value, ServletRequest servletRequest, ServletResponse servletResponse) {
 
         HttpServletRequest request = toHttp(servletRequest);
         HttpServletResponse response = toHttp(servletResponse);
 
         String name = getName();
+        String comment = getComment();
+        String domain = getDomain();
+        int version = getVersion();
         int maxAge = getMaxAge();
         String path = calculatePath(request);
 
@@ -299,12 +333,23 @@
         Cookie cookie = new Cookie(name, stringValue);
         cookie.setMaxAge(maxAge);
         cookie.setPath(path);
+
+        if (comment != null) {
+            cookie.setComment(comment);
+        }
+        if (domain != null) {
+            cookie.setDomain(domain);
+        }
+        if (version > DEFAULT_VERSION) {
+            cookie.setVersion(version);
+        }
+
         if (isSecure()) {
             cookie.setSecure(true);
         }
 
         response.addCookie(cookie);
-        
+
         if (log.isTraceEnabled()) {
             log.trace("Added Cookie [" + name + "] to path [" + path + "] with value [" +
                     stringValue + "] to the HttpServletResponse.");
@@ -322,6 +367,17 @@
             //retrieved cookie?)
             // my testing shows none of these browsers will remove cookie if setPath() is not invoked: FF3, Chrome, IE7, Safari windows
             cookie.setPath(calculatePath(request));
+
+            String domain = getDomain();
+            if (domain != null) {
+                cookie.setDomain(domain);
+            }
+
+            int version = getVersion();
+            if (version > DEFAULT_VERSION) {
+                cookie.setVersion(version);
+            }
+
             cookie.setSecure(isSecure());
             toHttp(response).addCookie(cookie);
             log.trace("Removed cookie[" + getName() + "] with path [" + calculatePath(request) + "] from HttpServletResponse.");

Modified: incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/session/DefaultWebSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/session/DefaultWebSessionManager.java?rev=781878&r1=781877&r2=781878&view=diff
==============================================================================
--- incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/session/DefaultWebSessionManager.java (original)
+++ incubator/jsecurity/trunk/web/src/main/java/org/apache/ki/web/session/DefaultWebSessionManager.java Fri Jun  5 00:21:40 2009
@@ -125,6 +125,10 @@
         getSessionIdCookieAttribute().setName(name);
     }
 
+    public void setSessionIdCookieDomain(String domain) {
+        getSessionIdCookieAttribute().setDomain(domain);
+    }
+
     public void setSessionIdCookiePath(String path) {
         getSessionIdCookieAttribute().setPath(path);
     }
@@ -133,10 +137,18 @@
         getSessionIdCookieAttribute().setMaxAge(maxAge);
     }
 
+    public void setSessionIdCookieVersion(int version) {
+        getSessionIdCookieAttribute().setVersion(version);
+    }
+
     public void setSessionIdCookieSecure(boolean secure) {
         getSessionIdCookieAttribute().setSecure(secure);
     }
 
+    public void setSessionIdCookieComment(String comment) {
+        getSessionIdCookieAttribute().setComment(comment);
+    }
+
     protected void ensureCookieSessionIdStore() {
         CookieAttribute<Serializable> cookieStore = getSessionIdCookieAttribute();
         if (cookieStore == null) {
@@ -155,7 +167,7 @@
     }
 
     protected void validateSessionOrigin(ServletRequest request, Session session)
-        throws HostUnauthorizedException {
+            throws HostUnauthorizedException {
         InetAddress requestIp = WebUtils.getInetAddress(request);
         InetAddress originIp = session.getHostAddress();
         Serializable sessionId = session.getId();
@@ -163,25 +175,25 @@
         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.";
+                        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.";
+                            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.";
+                        "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);
             }
         }
@@ -214,15 +226,15 @@
         Serializable id = cookieSessionIdAttribute.retrieveValue(request, response);
         if (id != null) {
             request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
-                KiHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
+                    KiHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
         } else {
             id = getSessionIdRequestParamAttribute().retrieveValue(request, response);
             if (id != null) {
                 request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
-                    KiHttpServletRequest.URL_SESSION_ID_SOURCE);
+                        KiHttpServletRequest.URL_SESSION_ID_SOURCE);
             }
         }
-        if ( id != null ) {
+        if (id != null) {
             request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID, id);
         }
         return id;
@@ -272,7 +284,7 @@
      *          if the caller is not authorized to access the session associated with the request.
      */
     public Session getSession(ServletRequest request, ServletResponse response)
-        throws InvalidSessionException, AuthorizationException {
+            throws InvalidSessionException, AuthorizationException {
 
         Session session = null;
         Serializable sessionId = getReferencedSessionId(request, response);
@@ -285,7 +297,7 @@
             } catch (InvalidSessionException ise) {
                 if (log.isTraceEnabled()) {
                     log.trace("Request Session with id [" + ise.getSessionId() + "] is invalid, message: [" +
-                        ise.getMessage() + "].  Removing any associated session cookie...");
+                            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:
@@ -319,7 +331,7 @@
         super.onStop(session);
         ServletRequest request = WebUtils.getRequiredServletRequest();
         ServletResponse response = WebUtils.getRequiredServletResponse();
-        removeSessionIdCookie(request,response);
+        removeSessionIdCookie(request, response);
         getSessionIdCookieAttribute().removeValue(request, response);
     }
 }