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 2010/04/23 22:42:44 UTC
svn commit: r937511 - in /incubator/shiro/trunk/web/src:
main/java/org/apache/shiro/web/ main/java/org/apache/shiro/web/attr/
main/java/org/apache/shiro/web/mgt/ main/java/org/apache/shiro/web/servlet/
test/java/org/apache/shiro/web/ test/java/org/apac...
Author: lhazlewood
Date: Fri Apr 23 20:42:43 2010
New Revision: 937511
URL: http://svn.apache.org/viewvc?rev=937511&view=rev
Log:
SHIRO-128:
Cookie/SimpleCookie addition removed need for WebRememberMeManager and the 'attr' components it used - Deprecated the WebRememberMeManager and all attr package components - to be removed immediately prior to the 1.0 release.
Added:
incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/SimpleCookieTest.java
Modified:
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebRememberMeManager.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/AbstractWebAttribute.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/CookieAttribute.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/RequestParamAttribute.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/WebAttribute.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java
incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/SimpleCookie.java
incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebRememberMeManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebRememberMeManager.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebRememberMeManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebRememberMeManager.java Fri Apr 23 20:42:43 2010
@@ -60,7 +60,10 @@ import javax.servlet.ServletResponse;
* @author Les Hazlewood
* @author Luis Arias
* @since 0.9
+ * @deprecated in favor of the {@link org.apache.shiro.web.mgt.CookieRememberMeManager}.
+ * THIS CLASS WILL BE DELETED PRIOR TO THE 1.0 RELEASE
*/
+@Deprecated
public class WebRememberMeManager extends AbstractRememberMeManager {
//TODO - complete JavaDoc
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/WebUtils.java Fri Apr 23 20:42:43 2010
@@ -21,9 +21,12 @@ package org.apache.shiro.web;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
+import org.apache.shiro.subject.SubjectContext;
import org.apache.shiro.util.StringUtils;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.web.filter.AccessControlFilter;
+import org.apache.shiro.web.subject.WebSubject;
+import org.apache.shiro.web.subject.WebSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -67,7 +70,7 @@ public class WebUtils {
/**
* {@link org.apache.shiro.session.Session Session} key used to save a request and later restore it, for example when redirecting to a
- * requested page after login, equal to <code>shiroSavedRequest</code>.
+ * requested page after login, equal to {@code shiroSavedRequest}.
*/
public static final String SAVED_REQUEST_KEY = "shiroSavedRequest";
@@ -232,6 +235,166 @@ public class WebUtils {
}
/**
+ * Returns {@code true} IFF the specified {@code SubjectContext}:
+ * <ol>
+ * <li>A {@link WebSubjectContext} instance</li>
+ * <li>The {@code WebSubjectContext}'s request/response pair are not null</li>
+ * <li>The request is an {@link HttpServletRequest} instance</li>
+ * <li>The response is an {@link HttpServletResponse} instance</li>
+ * </ol>
+ *
+ * @param context the SubjectContext to check to see if it is HTTP compatible.
+ * @return {@code true} IFF the specified context has HTTP request/response objects, {@code false} otherwise.
+ * @since 1.0
+ */
+ public static boolean isHttp(SubjectContext context) {
+ if (context instanceof WebSubjectContext) {
+ WebSubjectContext wsc = (WebSubjectContext) context;
+ ServletRequest request = wsc.getServletRequest();
+ ServletResponse response = wsc.getServletResponse();
+ return request != null && request instanceof HttpServletRequest &&
+ response != null && response instanceof HttpServletResponse;
+ }
+ return false;
+ }
+
+ /**
+ * Returns {@code true} IFF the specified {@code Subject}:
+ * <ol>
+ * <li>A {@link WebSubject} instance</li>
+ * <li>The {@code WebSubject}'s request/response pair are not null</li>
+ * <li>The request is an {@link HttpServletRequest} instance</li>
+ * <li>The response is an {@link HttpServletResponse} instance</li>
+ * </ol>
+ *
+ * @param subject the {@code Subject} instance to check to see if it is HTTP compatible
+ * @return {@code true} IFF the specified subject has HTTP request/response objects, {@code false} otherwise.
+ * @since 1.0
+ */
+ public static boolean isHttp(Subject subject) {
+ if (subject instanceof WebSubject) {
+ WebSubject ws = (WebSubject) subject;
+ ServletRequest request = ws.getServletRequest();
+ ServletResponse response = ws.getServletResponse();
+ return request != null && request instanceof HttpServletRequest &&
+ response != null && response instanceof HttpServletResponse;
+ }
+ return false;
+ }
+
+ /**
+ * Returns the {@code Subject}'s associated {@link HttpServletRequest} instance. This method will
+ * throw an {@link IllegalArgumentException} if the Subject is not a {@link WebSubject} instance or that
+ * {@code WebSubject} does not have an HTTP-compatible request object. Callers will usually want to call
+ * the {@link #isHttp(Subject) isHttp(subject)} method first to ensure this method can be called successfully.
+ *
+ * @param subject the subject instance from which to retrieve the {@code Subject}'s associated
+ * {@link HttpServletRequest} instance
+ * @return the subject's associated {@link HttpServletRequest} object.
+ * @throws IllegalArgumentException if the {@code Subject} is not a {@link WebSubject} or that {@code WebSubject}'s
+ * request is not an {@link HttpServletRequest}.
+ * @since 1.0
+ */
+ public static HttpServletRequest getHttpRequest(Subject subject) throws IllegalArgumentException {
+ if (!(subject instanceof WebSubject)) {
+ String msg = "Subject instance is not a " + WebSubject.class.getName() + " instance. This is required " +
+ "to obtain a ServletRequest and ServletResponse";
+ throw new IllegalArgumentException(msg);
+ }
+ WebSubject ws = (WebSubject) subject;
+ ServletRequest request = ws.getServletRequest();
+ if (request == null || !(request instanceof HttpServletRequest)) {
+ String msg = "WebSubject's ServletRequest is null or not an instance of HttpServletRequest.";
+ throw new IllegalArgumentException(msg);
+ }
+ return (HttpServletRequest) request;
+ }
+
+ /**
+ * Returns the {@code Subject}'s associated {@link HttpServletResponse} instance. This method will
+ * throw an {@link IllegalArgumentException} if the Subject is not a {@link WebSubject} instance or that
+ * {@code WebSubject} does not have an HTTP-compatible response object. Callers will usually want to call
+ * the {@link #isHttp(Subject) isHttp(subject)} method first to ensure this method can be called successfully.
+ *
+ * @param subject the subject instance from which to retrieve the {@code Subject}'s associated
+ * {@link HttpServletResponse} instance
+ * @return the subject's associated {@link HttpServletResponse} object.
+ * @throws IllegalArgumentException if the {@code Subject} is not a {@link WebSubject} or that {@code WebSubject}'s
+ * response is not an {@link HttpServletResponse}.
+ * @since 1.0
+ */
+ public static HttpServletResponse getHttpResponse(Subject subject) {
+ if (!(subject instanceof WebSubject)) {
+ String msg = "Subject instance is not a " + WebSubject.class.getName() + " instance. This is required " +
+ "to obtain a ServletRequest and ServletResponse";
+ throw new IllegalArgumentException(msg);
+ }
+ WebSubject ws = (WebSubject) subject;
+ ServletResponse response = ws.getServletResponse();
+ if (response == null || !(response instanceof HttpServletResponse)) {
+ String msg = "WebSubject's ServletResponse is null or not an instance of HttpServletResponse.";
+ throw new IllegalArgumentException(msg);
+ }
+ return (HttpServletResponse) response;
+ }
+
+ /**
+ * Returns the {@code SubjectContext}'s {@link HttpServletRequest} instance. This method will
+ * throw an {@link IllegalArgumentException} if the context is not a {@link WebSubjectContext} instance or that
+ * {@code WebSubjectContext} does not have an HTTP-compatible request object. Callers will usually want to call
+ * the {@link #isHttp(SubjectContext) isHttp(subjectContext)} method first to ensure this method can be called
+ * successfully.
+ *
+ * @param context the subjectContext instance from which to retrieve the associated {@link HttpServletRequest}
+ * @return the context's {@link HttpServletRequest} object.
+ * @throws IllegalArgumentException if the {@code SubjectContext} is not a {@link WebSubjectContext} or that
+ * {@code WebSubjectContext}'s request is not an {@link HttpServletRequest}.
+ * @since 1.0
+ */
+ public static HttpServletRequest getHttpRequest(SubjectContext context) {
+ if (!(context instanceof WebSubjectContext)) {
+ String msg = "SubjectContext instance is not a " + WebSubjectContext.class.getName() + " instance. " +
+ "This is required to obtain a ServletRequest and ServletResponse";
+ throw new IllegalArgumentException(msg);
+ }
+ WebSubjectContext wsc = (WebSubjectContext) context;
+ ServletRequest request = wsc.getServletRequest();
+ if (request == null || !(request instanceof HttpServletRequest)) {
+ String msg = "WebSubjectContext's ServletRequest is null or not an instance of HttpServletRequest.";
+ throw new IllegalArgumentException(msg);
+ }
+ return (HttpServletRequest) request;
+ }
+
+ /**
+ * Returns the {@code SubjectContext}'s {@link HttpServletResponse} instance. This method will
+ * throw an {@link IllegalArgumentException} if the context is not a {@link WebSubjectContext} instance or that
+ * {@code WebSubjectContext} does not have an HTTP-compatible response object. Callers will usually want to call
+ * the {@link #isHttp(SubjectContext) isHttp(subjectContext)} method first to ensure this method can be called
+ * successfully.
+ *
+ * @param context the subjectContext instance from which to retrieve the associated {@link HttpServletResponse}
+ * @return the context's {@link HttpServletResponse} object.
+ * @throws IllegalArgumentException if the {@code SubjectContext} is not a {@link WebSubjectContext} or that
+ * {@code WebSubjectContext}'s response is not an {@link HttpServletResponse}.
+ * @since 1.0
+ */
+ public static HttpServletResponse getHttpResponse(SubjectContext context) {
+ if (!(context instanceof WebSubjectContext)) {
+ String msg = "SubjectContext instance is not a " + WebSubjectContext.class.getName() + " instance. " +
+ "This is required to obtain a ServletRequest and ServletResponse";
+ throw new IllegalArgumentException(msg);
+ }
+ WebSubjectContext wsc = (WebSubjectContext) context;
+ ServletResponse response = wsc.getServletResponse();
+ if (response == null || !(response instanceof HttpServletResponse)) {
+ String msg = "WebSubjectContext's ServletResponse is null or not an instance of HttpServletResponse.";
+ throw new IllegalArgumentException(msg);
+ }
+ return (HttpServletResponse) response;
+ }
+
+ /**
* A convenience method that merely casts the incoming <code>ServletRequest</code> to an
* <code>HttpServletRequest</code>:
* <p/>
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/AbstractWebAttribute.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/AbstractWebAttribute.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/AbstractWebAttribute.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/AbstractWebAttribute.java Fri Apr 23 20:42:43 2010
@@ -18,15 +18,14 @@
*/
package org.apache.shiro.web.attr;
-import java.beans.PropertyEditor;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
+import org.apache.shiro.ShiroException;
+import org.apache.shiro.util.ClassUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.apache.shiro.ShiroException;
-import org.apache.shiro.util.ClassUtils;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.beans.PropertyEditor;
/**
* Convenient superclass for implementations of the {@link WebAttribute} interface. This class encapsulates
@@ -39,7 +38,10 @@ import org.apache.shiro.util.ClassUtils;
*
* @author Les Hazlewood
* @since 0.2
+ * @deprecated in favor of {@link org.apache.shiro.web.servlet.Cookie} and {@link org.apache.shiro.web.servlet.SimpleCookie}
+ * usages. THIS CLASS WILL BE DELETED PRIOR TO THE 1.0 RELEASE
*/
+@Deprecated
public abstract class AbstractWebAttribute<T> implements WebAttribute<T> {
//TODO - complete JavaDoc
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/CookieAttribute.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/CookieAttribute.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/CookieAttribute.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/CookieAttribute.java Fri Apr 23 20:42:43 2010
@@ -19,7 +19,6 @@
package org.apache.shiro.web.attr;
import org.apache.shiro.util.StringUtils;
-import static org.apache.shiro.web.WebUtils.toHttp;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -30,13 +29,18 @@ import javax.servlet.http.HttpServletReq
import javax.servlet.http.HttpServletResponse;
import java.beans.PropertyEditor;
+import static org.apache.shiro.web.WebUtils.toHttp;
+
/**
* A {@code CookieAttribute} stores an object as a {@link Cookie} for access on later requests.
*
* @author Les Hazlewood
* @author Peter Ledbrook
* @since 0.2
+ * @deprecated in favor of {@link org.apache.shiro.web.servlet.Cookie} and {@link org.apache.shiro.web.servlet.SimpleCookie}
+ * usages. THIS CLASS WILL BE DELETED PRIOR TO THE 1.0 RELEASE
*/
+@Deprecated
public class CookieAttribute<T> extends AbstractWebAttribute<T> {
//TODO - complete JavaDoc
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/RequestParamAttribute.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/RequestParamAttribute.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/RequestParamAttribute.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/RequestParamAttribute.java Fri Apr 23 20:42:43 2010
@@ -18,16 +18,19 @@
*/
package org.apache.shiro.web.attr;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
/**
* @author Les Hazlewood
* @since 0.2
+ * @deprecated in favor of {@link org.apache.shiro.web.servlet.Cookie} and {@link org.apache.shiro.web.servlet.SimpleCookie}
+ * usages. THIS CLASS WILL BE DELETED PRIOR TO THE 1.0 RELEASE
*/
+@Deprecated
public class RequestParamAttribute<T> extends AbstractWebAttribute<T> {
//TODO - complete JavaDoc
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/WebAttribute.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/WebAttribute.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/WebAttribute.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/attr/WebAttribute.java Fri Apr 23 20:42:43 2010
@@ -29,7 +29,10 @@ import javax.servlet.ServletResponse;
*
* @author Les Hazlewood
* @since 0.2
+ * @deprecated in favor of {@link org.apache.shiro.web.servlet.Cookie} and {@link org.apache.shiro.web.servlet.SimpleCookie}
+ * usages. THIS CLASS WILL BE DELETED PRIOR TO THE 1.0 RELEASE
*/
+@Deprecated
public interface WebAttribute<T> {
//TODO - complete JavaDoc
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/mgt/CookieRememberMeManager.java Fri Apr 23 20:42:43 2010
@@ -22,7 +22,6 @@ import org.apache.shiro.codec.Base64;
import org.apache.shiro.mgt.AbstractRememberMeManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.SubjectContext;
-import org.apache.shiro.util.CollectionUtils;
import org.apache.shiro.web.WebUtils;
import org.apache.shiro.web.servlet.Cookie;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
@@ -33,7 +32,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -43,13 +41,32 @@ import javax.servlet.http.HttpServletRes
* for later retrieval.
* <p/>
* Cookie attributes (path, domain, maxAge, etc) may be set on this class's default
- * {@link #getCookie() cookie} attribute. The cookie's default name is {@code rememberMe}.
+ * {@link #getCookie() cookie} attribute, which acts as a template to use to set all properties of outgoing cookies
+ * created by this implementation.
+ * <p/>
+ * The default cookie has the following attribute values set:
+ * <table>
+ * <tr>
+ * <th>Attribute Name</th>
+ * <th>Value</th>
+ * </tr>
+ * <tr><td>{@link Cookie#getName() name}</td>
+ * <td>{@code rememberMe}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link Cookie#getPath() path}</td>
+ * <td>{@code /}</td>
+ * </tr>
+ * <tr>
+ * <td>{@link Cookie#getMaxAge() maxAge}</td>
+ * <td>{@link Cookie#ONE_YEAR Cookie.ONE_YEAR}</td>
+ * </tr>
+ * </table>
* <p/>
* Note that because this class subclasses the {@link AbstractRememberMeManager} which already provides serialization
* and encryption logic, this class utilizes both for added security before setting the cookie value.
*
- * @author Les Hazlewood
- * @author Luis Arias
+ * @author The Apache Shiro Project (shiro-dev@incubator.apache.org)
* @since 1.0
*/
public class CookieRememberMeManager extends AbstractRememberMeManager {
@@ -65,30 +82,71 @@ public class CookieRememberMeManager ext
private Cookie cookie;
+ /**
+ * Constructs a new {@code CookieRememberMeManager} with a default {@code rememberMe} cookie template.
+ */
public CookieRememberMeManager() {
Cookie cookie = new SimpleCookie(DEFAULT_REMEMBER_ME_COOKIE_NAME);
cookie.setPath(Cookie.ROOT_PATH);
- //Peter (Apache Shiro developer) said that Jetty didn't like the CookieAttribute.INDEFINITE value
- // (Tomcat was ok with it), so just default to a few years for now. If anyone doesn't visit a site in 3 years
- // after last login, I doubt any Shiro users would mind their end-users to be forced to log in. - LAH.
- cookie.setMaxAge(Cookie.ONE_YEAR * 3);
+ //One year should be long enough - most sites won't object to requiring a user to log in if they haven't visited
+ //in a year:
+ cookie.setMaxAge(Cookie.ONE_YEAR);
this.cookie = cookie;
}
+ /**
+ * Returns the cookie 'template' that will be used to set all attributes of outgoing rememberMe cookies created by
+ * this {@code RememberMeManager}. Outgoing cookies will match this one except for the
+ * {@link Cookie#getValue() value} attribute, which is necessarily set dynamically at runtime.
+ * <p/>
+ * Please see the class-level JavaDoc for the default cookie's attribute values.
+ *
+ * @return the cookie 'template' that will be used to set all attributes of outgoing rememberMe cookies created by
+ * this {@code RememberMeManager}.
+ */
public Cookie getCookie() {
return cookie;
}
+ /**
+ * Sets the cookie 'template' that will be used to set all attributes of outgoing rememberMe cookies created by
+ * this {@code RememberMeManager}. Outgoing cookies will match this one except for the
+ * {@link Cookie#getValue() value} attribute, which is necessarily set dynamically at runtime.
+ * <p/>
+ * Please see the class-level JavaDoc for the default cookie's attribute values.
+ *
+ * @param cookie the cookie 'template' that will be used to set all attributes of outgoing rememberMe cookies created
+ * by this {@code RememberMeManager}.
+ */
public void setCookie(Cookie cookie) {
this.cookie = cookie;
}
+ /**
+ * Base64-encodes the specified serialized byte array and sets that base64-encoded String as the cookie value.
+ * <p/>
+ * The {@code subject} instance is expected to be a {@link WebSubject} instance with an HTTP Request/Response pair
+ * so an HTTP cookie can be set on the outgoing response. If it is not a {@code WebSubject} or that
+ * {@code WebSubject} does not have an HTTP Request/Response pair, this implementation does nothing.
+ *
+ * @param subject the Subject for which the identity is being serialized.
+ * @param serialized the serialized bytes to be persisted.
+ */
protected void rememberSerializedIdentity(Subject subject, byte[] serialized) {
- WebSubject webSubject = (WebSubject) subject;
- ServletRequest servletRequest = webSubject.getServletRequest();
- ServletResponse servletResponse = webSubject.getServletResponse();
- HttpServletRequest request = WebUtils.toHttp(servletRequest);
- HttpServletResponse response = WebUtils.toHttp(servletResponse);
+
+ if (!WebUtils.isHttp(subject)) {
+ if (log.isDebugEnabled()) {
+ String msg = "Subject argument is not an HTTP-aware instance. This is required to obtain a servlet " +
+ "request and response in order to set the rememberMe cookie. Returning immediately and " +
+ "ignoring rememberMe operation.";
+ log.debug(msg);
+ }
+ return;
+ }
+
+
+ HttpServletRequest request = WebUtils.getHttpRequest(subject);
+ HttpServletResponse response = WebUtils.getHttpResponse(subject);
//base 64 encode it and store as a cookie:
String base64 = Base64.encodeToString(serialized);
@@ -99,24 +157,8 @@ public class CookieRememberMeManager ext
cookie.saveTo(request, response);
}
- private ServletRequest getServletRequest(SubjectContext subjectContext) {
- ServletRequest request = null;
- if (subjectContext != null && subjectContext instanceof WebSubjectContext) {
- request = ((WebSubjectContext) subjectContext).getServletRequest();
- }
- return request;
- }
-
- private ServletResponse getServletResponse(SubjectContext subjectContext) {
- ServletResponse response = null;
- if (subjectContext != null && subjectContext instanceof WebSubjectContext) {
- response = ((WebSubjectContext) subjectContext).getServletResponse();
- }
- return response;
- }
-
- protected boolean isIdentityRemoved(SubjectContext subjectContext) {
- ServletRequest request = getServletRequest(subjectContext);
+ private boolean isIdentityRemoved(WebSubjectContext subjectContext) {
+ ServletRequest request = subjectContext.getServletRequest();
if (request != null) {
Boolean removed = (Boolean) request.getAttribute(ShiroHttpServletRequest.IDENTITY_REMOVED_KEY);
return removed != null && removed;
@@ -124,24 +166,41 @@ public class CookieRememberMeManager ext
return false;
}
+
+ /**
+ * Returns a previously serialized identity byte array or {@code null} if the byte array could not be acquired.
+ * This implementation retrieves an HTTP cookie, Base64-decodes the cookie value, and returns the resulting byte
+ * array.
+ * <p/>
+ * The {@code SubjectContext} instance is expected to be a {@link WebSubjectContext} instance with an HTTP
+ * Request/Response pair so an HTTP cookie can be retrieved from the incoming request. If it is not a
+ * {@code WebSubjectContext} or that {@code WebSubjectContext} does not have an HTTP Request/Response pair, this
+ * implementation returns {@code null}.
+ *
+ * @param subjectContext the contextual data, usually provided by a {@link Subject.Builder} implementation, that
+ * is being used to construct a {@link Subject} instance. To be used to assist with data
+ * lookup.
+ * @return a previously serialized identity byte array or {@code null} if the byte array could not be acquired.
+ */
protected byte[] getRememberedSerializedIdentity(SubjectContext subjectContext) {
- if (CollectionUtils.isEmpty(subjectContext)) {
- if (log.isTraceEnabled()) {
- log.trace("Null or empty SubjectContext - unable to retrieve request/response pair to obtain " +
- "a request-based identity. Returning null.");
+ if (!WebUtils.isHttp(subjectContext)) {
+ if (log.isDebugEnabled()) {
+ String msg = "SubjectContext argument is not an HTTP-aware instance. This is required to obtain a " +
+ "servlet request and response in order to retrieve the rememberMe cookie. Returning " +
+ "immediately and ignoring rememberMe operation.";
+ log.debug(msg);
}
return null;
}
- if (isIdentityRemoved(subjectContext)) {
+ WebSubjectContext wsc = (WebSubjectContext) subjectContext;
+ if (isIdentityRemoved(wsc)) {
return null;
}
- ServletRequest servletRequest = getServletRequest(subjectContext);
- ServletResponse servletResponse = getServletResponse(subjectContext);
- HttpServletRequest request = WebUtils.toHttp(servletRequest);
- HttpServletResponse response = WebUtils.toHttp(servletResponse);
+ HttpServletRequest request = WebUtils.getHttpRequest(wsc);
+ HttpServletResponse response = WebUtils.getHttpResponse(wsc);
String base64 = getCookie().readValue(request, response);
@@ -182,21 +241,48 @@ public class CookieRememberMeManager ext
return base64;
}
+ /**
+ * Removes the 'rememberMe' cookie from the associated {@link WebSubject}'s request/response pair.
+ * <p/>
+ * The {@code subject} instance is expected to be a {@link WebSubject} instance with an HTTP Request/Response pair.
+ * If it is not a {@code WebSubject} or that {@code WebSubject} does not have an HTTP Request/Response pair, this
+ * implementation does nothing.
+ *
+ * @param subject the subject instance for which identity data should be forgotten from the underlying persistence
+ */
protected void forgetIdentity(Subject subject) {
- WebSubject webSubject = (WebSubject) subject;
- ServletRequest request = webSubject.getServletRequest();
- ServletResponse response = webSubject.getServletResponse();
- forgetIdentity(request, response);
+ if (WebUtils.isHttp(subject)) {
+ HttpServletRequest request = WebUtils.getHttpRequest(subject);
+ HttpServletResponse response = WebUtils.getHttpResponse(subject);
+ forgetIdentity(request, response);
+ }
}
+ /**
+ * Removes the 'rememberMe' cookie from the associated {@link WebSubjectContext}'s request/response pair.
+ * <p/>
+ * The {@code SubjectContext} instance is expected to be a {@link WebSubjectContext} instance with an HTTP
+ * Request/Response pair. If it is not a {@code WebSubjectContext} or that {@code WebSubjectContext} does not
+ * have an HTTP Request/Response pair, this implementation does nothing.
+ *
+ * @param subjectContext the contextual data, usually provided by a {@link Subject.Builder} implementation
+ */
protected void forgetIdentity(SubjectContext subjectContext) {
- ServletRequest request = getServletRequest(subjectContext);
- ServletResponse response = getServletResponse(subjectContext);
- forgetIdentity(request, response);
+ if (WebUtils.isHttp(subjectContext)) {
+ HttpServletRequest request = WebUtils.getHttpRequest(subjectContext);
+ HttpServletResponse response = WebUtils.getHttpResponse(subjectContext);
+ forgetIdentity(request, response);
+ }
}
- protected void forgetIdentity(ServletRequest request, ServletResponse response) {
- getCookie().removeFrom(WebUtils.toHttp(request), WebUtils.toHttp(response));
+ /**
+ * Removes the rememberMe cookie from the given request/response pair.
+ *
+ * @param request the incoming HTTP servlet request
+ * @param response the outgoing HTTP servlet response
+ */
+ private void forgetIdentity(HttpServletRequest request, HttpServletResponse response) {
+ getCookie().removeFrom(request, response);
}
}
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java Fri Apr 23 20:42:43 2010
@@ -532,7 +532,8 @@ public class ShiroFilter extends OncePer
protected ThreadState bind(ServletRequest request, ServletResponse response) {
SecurityManager securityManager = getSecurityManager();
ThreadContext.bind(securityManager);
- //currently the WebRememberMeManager needs the request/response bound in order to create the subject instance:
+ //TODO - remove:
+ //currently the CookieRememberMeManager needs the request/response bound in order to create the subject instance:
WebUtils.bind(request);
WebUtils.bind(response);
Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/SimpleCookie.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/SimpleCookie.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/SimpleCookie.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/SimpleCookie.java Fri Apr 23 20:42:43 2010
@@ -153,7 +153,7 @@ public class SimpleCookie implements Coo
path = StringUtils.clean(request.getContextPath());
}
- //fix for http://issues.apache.org/jira/browse/JSEC-34:
+ //fix for http://issues.apache.org/jira/browse/SHIRO-9:
if (path == null) {
path = ROOT_PATH;
}
Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/WebRememberMeManagerTest.java Fri Apr 23 20:42:43 2010
@@ -39,11 +39,12 @@ import static org.junit.Assert.assertNot
import static org.junit.Assert.assertTrue;
/**
- * TODO - class javadoc
- *
* @author Les Hazlewood
* @since Apr 23, 2008 9:16:47 AM
+ * @deprecated in favor of {@link org.apache.shiro.web.mgt.CookieRememberMeManagerTest}.
+ * THIS CLASS WILL BE DELETED PRIOR TO THE 1.0 RELEASE
*/
+@Deprecated
public class WebRememberMeManagerTest {
@Test
Modified: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java?rev=937511&r1=937510&r2=937511&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java (original)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/config/IniFilterChainResolverFactoryTest.java Fri Apr 23 20:42:43 2010
@@ -22,10 +22,6 @@ import org.apache.shiro.config.Configura
import org.apache.shiro.config.Ini;
import org.apache.shiro.web.WebTest;
import org.apache.shiro.web.filter.mgt.FilterChainResolver;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
import org.junit.Before;
import org.junit.Test;
@@ -33,6 +29,11 @@ import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import java.util.Map;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
/**
* Tests for the {@link IniFilterChainResolverFactory}.
*
@@ -90,7 +91,7 @@ public class IniFilterChainResolverFacto
Ini ini = new Ini();
String config =
"[filters]\n" +
- "test = org.apache.shiro.web.attr.CookieAttribute\n" + //any non-Filter will do
+ "test = org.apache.shiro.web.servlet.SimpleCookie\n" + //any non-Filter will do
"[urls]\n" +
"/index.html = anon";
ini.load(config);
Added: incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/SimpleCookieTest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/SimpleCookieTest.java?rev=937511&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/SimpleCookieTest.java (added)
+++ incubator/shiro/trunk/web/src/test/java/org/apache/shiro/web/servlet/SimpleCookieTest.java Fri Apr 23 20:42:43 2010
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2008 Les Hazlewood
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.shiro.web.servlet;
+
+import junit.framework.TestCase;
+import org.easymock.IArgumentMatcher;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import static org.easymock.EasyMock.*;
+
+/**
+ * TODO - Class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since Apr 22, 2010 9:40:47 PM
+ */
+public class SimpleCookieTest extends TestCase {
+
+ private SimpleCookie cookie;
+
+ private HttpServletRequest mockRequest;
+ private HttpServletResponse mockResponse;
+
+ @Before
+ public void setUp() throws Exception {
+ this.mockRequest = createMock(HttpServletRequest.class);
+ this.mockResponse = createMock(HttpServletResponse.class);
+ this.cookie = new SimpleCookie("test");
+ }
+
+ @Test
+ //Verifies fix for JSEC-94
+ public void testRemoveValue() throws Exception {
+
+ javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie("test", "blah");
+ cookie.setMaxAge(2351234); //doesn't matter what the time is
+ javax.servlet.http.Cookie[] cookies = new javax.servlet.http.Cookie[]{cookie};
+
+ expect(mockRequest.getCookies()).andReturn(cookies);
+ //no path set on the cookie, so we expect to retrieve it from the context path
+ expect(mockRequest.getContextPath()).andReturn("/somepath").times(1);
+ mockResponse.addCookie(cookie);
+ replay(mockRequest);
+ replay(mockResponse);
+
+ this.cookie.removeFrom(mockRequest, mockResponse);
+
+ verify(mockRequest);
+ verify(mockResponse);
+
+ assertTrue(cookie.getMaxAge() == 0);
+ assertTrue(cookie.getPath().equals("/somepath"));
+ }
+
+ private void testContextPath(String contextPath) {
+ this.cookie.setValue("blah");
+
+ javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie("test", "blah");
+ cookie.setMaxAge(-1);
+ cookie.setPath("/");
+
+ expect(mockRequest.getContextPath()).andReturn(contextPath);
+
+ mockResponse.addCookie(eqCookie(cookie));
+
+ replay(mockRequest);
+ replay(mockResponse);
+
+ this.cookie.saveTo(mockRequest, mockResponse);
+
+ verify(mockRequest);
+ verify(mockResponse);
+ }
+
+ @Test
+ /** Verifies fix for <a href="http://issues.apache.org/jira/browse/JSEC-34">JSEC-34</a> (1 of 2)*/
+ public void testEmptyContextPath() throws Exception {
+ testContextPath("");
+ }
+
+
+ @Test
+ /** Verifies fix for <a href="http://issues.apache.org/jira/browse/JSEC-34">JSEC-34</a> (2 of 2)*/
+ public void testNullContextPath() throws Exception {
+ testContextPath(null);
+ }
+
+ private static <T extends javax.servlet.http.Cookie> T eqCookie(final T in) {
+ reportMatcher(new IArgumentMatcher() {
+ public boolean matches(Object o) {
+ javax.servlet.http.Cookie c = (javax.servlet.http.Cookie) o;
+ return c.getName().equals(in.getName()) &&
+ c.getValue().equals(in.getValue()) &&
+ c.getPath().equals(in.getPath()) &&
+ c.getMaxAge() == in.getMaxAge() &&
+ c.getSecure() == in.getSecure() &&
+ c.getValue().equals(in.getValue());
+ }
+
+ public void appendTo(StringBuffer sb) {
+ sb.append("eqCookie(");
+ sb.append(in.getClass().getName());
+ sb.append(")");
+
+ }
+ });
+ return null;
+ }
+
+ @Test
+ //Verifies fix for JSEC-64
+ public void testRemoveValueWithNullContext() throws Exception {
+
+ javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie("test", "blah");
+ cookie.setMaxAge(2351234); //doesn't matter what the time is
+ javax.servlet.http.Cookie[] cookies = new javax.servlet.http.Cookie[]{cookie};
+
+ expect(mockRequest.getCookies()).andReturn(cookies);
+ //no path set on the cookie, so we expect to retrieve it from the context path
+ expect(mockRequest.getContextPath()).andReturn(null).times(1);
+ mockResponse.addCookie(cookie);
+ replay(mockRequest);
+ replay(mockResponse);
+
+ this.cookie.removeFrom(mockRequest, mockResponse);
+
+ verify(mockRequest);
+ verify(mockResponse);
+
+ assertTrue(cookie.getMaxAge() == 0);
+ assertTrue(cookie.getPath().equals("/"));
+ }
+
+}