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/05/14 02:05:56 UTC
svn commit: r944065 -
/incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.java
Author: lhazlewood
Date: Fri May 14 00:05:56 2010
New Revision: 944065
URL: http://svn.apache.org/viewvc?rev=944065&view=rev
Log:
SHIRO-157 - implemented functionality. Remembered principals will automatically be added to the session, and if there isn't a session, a new one will be created to receive the principals. This ensures that the RememberMeManager will only be consulted if a session does not yet have an identity associated with it.
Modified:
incubator/shiro/trunk/core/src/main/java/org/apache/shiro/mgt/DefaultSecurityManager.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=944065&r1=944064&r2=944065&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 Fri May 14 00:05:56 2010
@@ -166,7 +166,7 @@ public class DefaultSecurityManager exte
PrincipalCollection principals = subject.getPrincipals();
if (principals != null && !principals.isEmpty()) {
Session session = subject.getSession();
- session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, principals);
+ bindPrincipalsToSession(principals, session);
} else {
Session session = subject.getSession(false);
if (session != null) {
@@ -185,6 +185,16 @@ public class DefaultSecurityManager exte
}
}
+ private void bindPrincipalsToSession(PrincipalCollection principals, Session session) {
+ if (session == null) {
+ throw new IllegalArgumentException("Session argument cannot be null.");
+ }
+ if (CollectionUtils.isEmpty(principals)) {
+ throw new IllegalArgumentException("Principals cannot be null or empty.");
+ }
+ session.setAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY, principals);
+ }
+
protected void rememberMeSuccessfulLogin(AuthenticationToken token, AuthenticationInfo info, Subject subject) {
RememberMeManager rmm = getRememberMeManager();
if (rmm != null) {
@@ -387,7 +397,9 @@ public class DefaultSecurityManager exte
* <li>Check the context to see if it can already {@link SubjectContext#resolvePrincipals resolve 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, place the remembered {@link PrincipalCollection} in the context and return the context.</li>
+ * non-null value, place the remembered {@link PrincipalCollection} in the context.</li>
+ * <li>If the remembered identity is discovered, associate it with the session so eliminate unnecessary
+ * rememberMe accesses for the remainder of the session</li>
* </ol>
*
* @param context the subject context data that may provide (directly or indirectly through one of its values) a
@@ -405,6 +417,7 @@ public class DefaultSecurityManager exte
log.debug("Found remembered PrincipalCollection. Adding to the context to be used " +
"for subject construction by the SubjectFactory.");
context.setPrincipals(principals);
+ bindPrincipalsToSession(principals, context);
} else {
log.trace("No remembered identity found. Returning original context.");
}
@@ -414,6 +427,41 @@ public class DefaultSecurityManager exte
}
/**
+ * Satisfies SHIRO-157: associate a known identity with the current session to ensure that we don't need to
+ * continually perform rememberMe operations for sessions that already have an identity. Doing this prevents the
+ * need to continually reference, decrypt and deserialize the rememberMe cookie every time - something that can
+ * be computationally expensive if many requests are intercepted.
+ * <p/>
+ * Note that if the SubjectContext cannot {@link SubjectContext#resolveSession resolve} a session, a new session
+ * will be created receive the principals and then appended to the SubjectContext so it can be used later when
+ * constructing the Subject.
+ *
+ * @param principals the non-null, non-empty principals to bind to the SubjectContext's session
+ * @param context the context to use to locate or create a session to which the principals will be saved
+ * @since 1.0
+ */
+ private void bindPrincipalsToSession(PrincipalCollection principals, SubjectContext context) {
+ SecurityManager securityManager = context.resolveSecurityManager();
+ if (securityManager == null) {
+ throw new IllegalStateException("SecurityManager instance should already be present in the " +
+ "SubjectContext argument.");
+ }
+ Session session = context.resolveSession();
+ if (session == null) {
+ log.trace("No session in the current subject context. One will be created to persist principals [{}] " +
+ "Doing this prevents unnecessary repeated RememberMe operations since an identity has been " +
+ "discovered.", principals);
+ //no session - start one:
+ String host = context.resolveHost();
+ Serializable sessionId = start(host);
+ session = new DelegatingSession(securityManager, sessionId, host);
+ context.setSession(session);
+ log.debug("Created session with id {} to retain discovered principals {}", sessionId, principals);
+ }
+ bindPrincipalsToSession(principals, session);
+ }
+
+ /**
* Allows subclasses to react to the fact that a specified/referenced session id was invalid. Default
* implementation does nothing (no-op).
*