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/08/27 23:38:41 UTC
svn commit: r808644 - in
/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt:
DefaultSecurityManager.java SecurityManager.java
Author: lhazlewood
Date: Thu Aug 27 21:38:41 2009
New Revision: 808644
URL: http://svn.apache.org/viewvc?rev=808644&view=rev
Log:
SHIRO-91 - submitted fix for rememberMe
Modified:
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java
Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java?rev=808644&r1=808643&r2=808644&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 Aug 27 21:38:41 2009
@@ -29,12 +29,12 @@
import org.apache.shiro.session.mgt.DelegatingSession;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
-import org.apache.shiro.util.ThreadContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.Serializable;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@@ -188,72 +188,11 @@
getRememberMeManagerForCipherAttributes().setDecryptionCipherKeyBase64(base64);
}
- protected Serializable getCurrentSessionId() {
- return ThreadContext.getSessionId();
- }
-
protected Session getSession(Serializable id) {
checkValid(id);
return new DelegatingSession(this, id);
}
- protected Session getCurrentSession() {
- Serializable sessionId = getCurrentSessionId();
- Session session = null;
- if (sessionId != null) {
- try {
- session = getSession(sessionId);
- } catch (InvalidSessionException e) {
- if (log.isDebugEnabled()) {
- log.debug("Session id referenced on the current thread [" + sessionId + "] is invalid. " +
- "Ignoring and creating a new Subject instance to continue. This message can be " +
- "safely ignored.", e);
- }
- } catch (AuthorizationException e) {
- if (log.isWarnEnabled()) {
- log.warn("Session id referenced on the current thread [" + sessionId + "] is not allowed to be " +
- "referenced. Ignoring and creating a Subject instance without a session to continue.", e);
- }
- }
- }
- return 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 #createSubject(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);
- }
- return createSubject(context);
- }
-
/**
* Creates a {@code Subject} instance for the user represented by the given method arguments.
*
@@ -386,9 +325,11 @@
/**
* 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>
+ * passing it to the {@link #resolveSession(Map)} method. The
+ * return value from that call is then used to attempt to resolve the subject identity via the
+ * {@link #resolvePrincipals(java.util.Map)} method. The return value from that call is then used to create
+ * the {@code Subject} instance by calling
+ * <code>{@link #getSubjectFactory() getSubjectFactory()}.{@link SubjectFactory#createSubject(java.util.Map) createSubject}(resolvedContext);</code>
*
* @param context any data needed to direct how the Subject should be constructed.
* @return the {@code Subject} instance reflecting the specified initialization data.
@@ -399,7 +340,10 @@
//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);
+ Map resolved = resolveSession(context);
+ //Similarly, the SubjectFactory should not have any concept of RememberMe - translate that here first
+ //if possible before handing off to the SubjectFactory:
+ resolved = resolvePrincipals(resolved);
return getSubjectFactory().createSubject(resolved);
}
@@ -415,14 +359,14 @@
* <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.
+ * returns the Map method argument unaltered.
*
* @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) {
+ protected Map resolveSession(Map context) {
if (context.containsKey(SubjectFactory.SESSION)) {
log.debug("Context already contains a session. Returning.");
return context;
@@ -436,7 +380,7 @@
Session session = getSession(sessionId);
copy.put(SubjectFactory.SESSION, session);
} catch (InvalidSessionException e) {
- onInvalidSessionId(sessionId);
+ onInvalidSessionId(sessionId, e);
log.debug("Context referenced sessionId is invalid. Ignoring and creating an anonymous " +
"(session-less) Subject instance.", e);
}
@@ -445,12 +389,84 @@
}
/**
- * Allows subclasses to react to the fact that a provided session id was invalid.
+ * Heuristically determines if the specified subject map can resolve a Subject identity ({@link PrincipalCollection})
+ * either directly or indirectly by value association. This implementation returns {@code true} in the following
+ * two cases, {@code false} otherwise:
+ * <ol>
+ * <li>If the context {@link Map#containsKey contains} a key {@link SubjectFactory#PRINCIPALS}, it is assumed
+ * the identity has been explicitly provided already.</li>
+ * <li>If the context has a {@link Session} under the {@link SubjectFactory#SESSION} key, it attempts to resolve
+ * any identity associated with that {@code Session} instance. If one can be found in the {@code Session}, it is
+ * assumed that {@code Session} identity should be used/retained.</li>
+ * </ol>
+ *
+ * @param context the subject context data that may provide (directly or indirectly through one of its values) a
+ * {@link PrincipalCollection} identity.
+ * @return {@code true} if an identity can be resolved, {@code false} otherwise.
+ * @since 1.0
+ */
+ protected boolean containsIdentity(Map context) {
+ if (context.containsKey(SubjectFactory.PRINCIPALS)) {
+ log.trace("Context already contains an explicit identity.");
+ return true;
+ }
+ if (context.containsKey(SubjectFactory.SESSION)) {
+ Session session = (Session) context.get(SubjectFactory.SESSION);
+ if (session != null) {
+ Object principals = session.getAttribute(SessionSubjectBinder.PRINCIPALS_SESSION_KEY);
+ if (principals != null) {
+ log.trace("Context already contains an implicit (session-based) identity.");
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Attempts to resolve an identity (a {@link PrincipalCollection}) for the context using heuristics. The
+ * implementation strategy:
+ * <ol>
+ * <li>Check the context to see if it already {@link #containsIdentity(java.util.Map) contains an identity}. If
+ * so, this method does nothing and returns the method argument unaltered.</li>
+ * <li>Check for a RememberMe identity by calling {@link #getRememberedIdentity()}. If that method returns a
+ * non-null value, create a <em>copy</em> of the method argument, and place the remembered {@link PrincipalCollection}
+ * in the copied context map under the {@link SubjectFactory#PRINCIPALS} key and return that copied context.</li>
+ * </ol>
+ *
+ * @param context the subject context data that may provide (directly or indirectly through one of its values) a
+ * {@link PrincipalCollection} identity.
+ * @return The context Map to use to pass to a {@link SubjectFactory} for subject creation.
+ * @since 1.0
+ */
+ @SuppressWarnings({"unchecked"})
+ protected Map resolvePrincipals(Map context) {
+ Map ctx = context;
+
+ if (!containsIdentity(context)) {
+ log.trace("No identity (PrincipalCollection) found in the context. Looking for a remembered identity.");
+ PrincipalCollection principals = getRememberedIdentity();
+ if (principals != null) {
+ log.debug("Found remembered PrincipalCollection. Adding to the context to be used " +
+ "for subject construction by the SubjectFactory.");
+ ctx = new HashMap(context);
+ ctx.put(SubjectFactory.PRINCIPALS, principals);
+ }
+ }
+
+ log.trace("No remembered identity found. Returning original context.");
+ return ctx;
+ }
+
+ /**
+ * Allows subclasses to react to the fact that a specified/referenced session id was invalid. Default
+ * implementation does nothing (no-op).
*
* @param sessionId the session id that was discovered to be invalid (no session, expired, etc).
+ * @param e the exception thrown upon encountering the invalid session id
* @since 1.0
*/
- protected void onInvalidSessionId(Serializable sessionId) {
+ protected void onInvalidSessionId(Serializable sessionId, InvalidSessionException e) {
}
/**
@@ -552,24 +568,13 @@
return null;
}
- @Deprecated
- protected Subject getSubject(boolean create) {
- Subject subject = getSubjectBinder().getSubject();
- if (subject == null && create) {
- subject = createSubject();
- bind(subject);
- }
- return subject;
- }
-
public Subject getSubject() {
- return getSubject(true);
- /*Subject subject = getSubjectBinder().getSubject();
+ Subject subject = getSubjectBinder().getSubject();
if (subject == null) {
- subject = getSubjectFactory().createSubject(Collections.EMPTY_MAP);
+ subject = createSubject(Collections.EMPTY_MAP);
bind(subject);
}
- return subject;*/
+ return subject;
}
/**
Modified: incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java?rev=808644&r1=808643&r2=808644&view=diff
==============================================================================
--- incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java (original)
+++ incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/SecurityManager.java Thu Aug 27 21:38:41 2009
@@ -128,7 +128,4 @@
*/
Subject createSubject(Map context);
- //Subject getSubjectBySessionId(Serializable sessionId);
-
- //Subject getSubject(PrincipalCollection principals);
}