SEC-1695: Allow customization of the session key under which the SecurityContext is stored.
This commit is contained in:
+28
-27
@@ -17,9 +17,7 @@ package org.springframework.security.authentication.jaas;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
import javax.security.auth.callback.Callback;
|
||||
import javax.security.auth.callback.CallbackHandler;
|
||||
@@ -54,7 +52,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* <p>This implementation is backed by a <a
|
||||
* href="http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/JAASRefGuide.html">JAAS</a> configuration that is provided by
|
||||
* a subclass's implementation of {@link #createLoginContext(CallbackHandler)}.
|
||||
*
|
||||
*
|
||||
* <p>When using JAAS login modules as the authentication source, sometimes the
|
||||
* <a href="http://java.sun.com/j2se/1.5.0/docs/api/javax/security/auth/login/LoginContext.html">LoginContext</a> will
|
||||
* require <i>CallbackHandler</i>s. The AbstractJaasAuthenticationProvider uses an internal
|
||||
@@ -91,7 +89,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* </list>
|
||||
* </property>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @author Ray Krueger
|
||||
* @author Rob Winch
|
||||
*/
|
||||
@@ -190,7 +188,7 @@ ApplicationEventPublisherAware, InitializingBean, ApplicationListener<SessionDes
|
||||
|
||||
/**
|
||||
* Creates the LoginContext to be used for authentication.
|
||||
*
|
||||
*
|
||||
* @param handler The CallbackHandler that should be used for the LoginContext (never <code>null</code>).
|
||||
* @return the LoginContext to use for authentication.
|
||||
* @throws LoginException
|
||||
@@ -198,39 +196,42 @@ ApplicationEventPublisherAware, InitializingBean, ApplicationListener<SessionDes
|
||||
protected abstract LoginContext createLoginContext(CallbackHandler handler) throws LoginException;
|
||||
|
||||
/**
|
||||
* Handles the logout by getting the SecurityContext for the session that was destroyed. <b>MUST NOT use
|
||||
* SecurityContextHolder as we are logging out a session that is not related to the current user.</b>
|
||||
* Handles the logout by getting the security contexts for the destroyed session and invoking
|
||||
* {@code LoginContext.logout()} for any which contain a {@code JaasAuthenticationToken}.
|
||||
*
|
||||
* @param event
|
||||
*
|
||||
* @param event the session event which contains the current session
|
||||
*/
|
||||
protected void handleLogout(SessionDestroyedEvent event) {
|
||||
SecurityContext context = event.getSecurityContext();
|
||||
List<SecurityContext> contexts = event.getSecurityContexts();
|
||||
|
||||
if (context == null) {
|
||||
log.debug("The destroyed session has no SecurityContext");
|
||||
if (contexts.isEmpty()) {
|
||||
log.debug("The destroyed session has no SecurityContexts");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Authentication auth = context.getAuthentication();
|
||||
for(SecurityContext context : contexts) {
|
||||
Authentication auth = context.getAuthentication();
|
||||
|
||||
if ((auth != null) && (auth instanceof JaasAuthenticationToken)) {
|
||||
JaasAuthenticationToken token = (JaasAuthenticationToken) auth;
|
||||
if ((auth != null) && (auth instanceof JaasAuthenticationToken)) {
|
||||
JaasAuthenticationToken token = (JaasAuthenticationToken) auth;
|
||||
|
||||
try {
|
||||
LoginContext loginContext = token.getLoginContext();
|
||||
boolean debug = log.isDebugEnabled();
|
||||
if (loginContext != null) {
|
||||
if (debug) {
|
||||
log.debug("Logging principal: [" + token.getPrincipal() + "] out of LoginContext");
|
||||
try {
|
||||
LoginContext loginContext = token.getLoginContext();
|
||||
boolean debug = log.isDebugEnabled();
|
||||
if (loginContext != null) {
|
||||
if (debug) {
|
||||
log.debug("Logging principal: [" + token.getPrincipal() + "] out of LoginContext");
|
||||
}
|
||||
loginContext.logout();
|
||||
} else if (debug) {
|
||||
log.debug("Cannot logout principal: [" + token.getPrincipal() + "] from LoginContext. "
|
||||
+ "The LoginContext is unavailable");
|
||||
}
|
||||
loginContext.logout();
|
||||
} else if (debug) {
|
||||
log.debug("Cannot logout principal: [" + token.getPrincipal() + "] from LoginContext. "
|
||||
+ "The LoginContext is unavailable");
|
||||
} catch (LoginException e) {
|
||||
log.warn("Error error logging out of LoginContext", e);
|
||||
}
|
||||
} catch (LoginException e) {
|
||||
log.warn("Error error logging out of LoginContext", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+7
-3
@@ -3,6 +3,8 @@ package org.springframework.security.core.session;
|
||||
import org.springframework.context.ApplicationEvent;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Generic "session termination" event which indicates that a session (potentially
|
||||
* represented by a security context) has ended.
|
||||
@@ -17,11 +19,13 @@ public abstract class SessionDestroyedEvent extends ApplicationEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the <tt>SecurityContext</tt> under which the session was running.
|
||||
* Provides the {@code SecurityContext} instances which were associated with the destroyed session. Usually there
|
||||
* will be only one security context per session.
|
||||
*
|
||||
* @return the <tt>SecurityContext</tt> associated with the session, or null if there is no context.
|
||||
* @return the {@code SecurityContext} instances which were stored in the current session (an empty list if there
|
||||
* are none).
|
||||
*/
|
||||
public abstract SecurityContext getSecurityContext();
|
||||
public abstract List<SecurityContext> getSecurityContexts();
|
||||
|
||||
/**
|
||||
* @return the identifier associated with the destroyed session.
|
||||
|
||||
+14
-14
@@ -27,7 +27,7 @@ import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.*;
|
||||
|
||||
import javax.security.auth.login.AppConfigurationEntry;
|
||||
import javax.security.auth.login.AppConfigurationEntry.LoginModuleControlFlag;
|
||||
@@ -136,13 +136,13 @@ public class DefaultJaasAuthenticationProviderTests {
|
||||
JaasAuthenticationToken token = mock(JaasAuthenticationToken.class);
|
||||
LoginContext context = mock(LoginContext.class);
|
||||
|
||||
when(event.getSecurityContext()).thenReturn(securityContext);
|
||||
when(event.getSecurityContexts()).thenReturn(Arrays.asList(securityContext));
|
||||
when(securityContext.getAuthentication()).thenReturn(token);
|
||||
when(token.getLoginContext()).thenReturn(context);
|
||||
|
||||
provider.onApplicationEvent(event);
|
||||
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(securityContext).getAuthentication();
|
||||
verify(token).getLoginContext();
|
||||
verify(context).logout();
|
||||
@@ -155,7 +155,7 @@ public class DefaultJaasAuthenticationProviderTests {
|
||||
|
||||
provider.handleLogout(event);
|
||||
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(log).debug(anyString());
|
||||
verifyNoMoreInteractions(event);
|
||||
}
|
||||
@@ -165,12 +165,12 @@ public class DefaultJaasAuthenticationProviderTests {
|
||||
SessionDestroyedEvent event = mock(SessionDestroyedEvent.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
|
||||
when(event.getSecurityContext()).thenReturn(securityContext);
|
||||
when(event.getSecurityContexts()).thenReturn(Arrays.asList(securityContext));
|
||||
|
||||
provider.handleLogout(event);
|
||||
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(securityContext).getAuthentication();
|
||||
verifyNoMoreInteractions(event, securityContext);
|
||||
}
|
||||
@@ -180,13 +180,13 @@ public class DefaultJaasAuthenticationProviderTests {
|
||||
SessionDestroyedEvent event = mock(SessionDestroyedEvent.class);
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
|
||||
when(event.getSecurityContext()).thenReturn(securityContext);
|
||||
when(event.getSecurityContexts()).thenReturn(Arrays.asList(securityContext));
|
||||
when(securityContext.getAuthentication()).thenReturn(token);
|
||||
|
||||
provider.handleLogout(event);
|
||||
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(securityContext).getAuthentication();
|
||||
verifyNoMoreInteractions(event, securityContext);
|
||||
}
|
||||
@@ -197,11 +197,11 @@ public class DefaultJaasAuthenticationProviderTests {
|
||||
SecurityContext securityContext = mock(SecurityContext.class);
|
||||
JaasAuthenticationToken token = mock(JaasAuthenticationToken.class);
|
||||
|
||||
when(event.getSecurityContext()).thenReturn(securityContext);
|
||||
when(event.getSecurityContexts()).thenReturn(Arrays.asList(securityContext));
|
||||
when(securityContext.getAuthentication()).thenReturn(token);
|
||||
|
||||
provider.onApplicationEvent(event);
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(securityContext).getAuthentication();
|
||||
verify(token).getLoginContext();
|
||||
|
||||
@@ -216,14 +216,14 @@ public class DefaultJaasAuthenticationProviderTests {
|
||||
LoginContext context = mock(LoginContext.class);
|
||||
LoginException loginException = new LoginException("Failed Login");
|
||||
|
||||
when(event.getSecurityContext()).thenReturn(securityContext);
|
||||
when(event.getSecurityContexts()).thenReturn(Arrays.asList(securityContext));
|
||||
when(securityContext.getAuthentication()).thenReturn(token);
|
||||
when(token.getLoginContext()).thenReturn(context);
|
||||
doThrow(loginException).when(context).logout();
|
||||
|
||||
provider.onApplicationEvent(event);
|
||||
|
||||
verify(event).getSecurityContext();
|
||||
verify(event).getSecurityContexts();
|
||||
verify(securityContext).getAuthentication();
|
||||
verify(token).getLoginContext();
|
||||
verify(context).logout();
|
||||
|
||||
+4
-2
@@ -41,6 +41,8 @@ import org.springframework.security.core.AuthenticationException;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.AuthorityUtils;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextImpl;
|
||||
import org.springframework.security.core.session.SessionDestroyedEvent;
|
||||
|
||||
@@ -244,11 +246,11 @@ public class JaasAuthenticationProviderTests {
|
||||
|
||||
JaasAuthenticationToken token = new JaasAuthenticationToken(null, null, loginContext);
|
||||
|
||||
SecurityContextImpl context = new SecurityContextImpl();
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(token);
|
||||
|
||||
SessionDestroyedEvent event = mock(SessionDestroyedEvent.class);
|
||||
when(event.getSecurityContext()).thenReturn(context);
|
||||
when(event.getSecurityContexts()).thenReturn(Arrays.asList(context));
|
||||
|
||||
jaasProvider.handleLogout(event);
|
||||
|
||||
|
||||
+1
-1
@@ -58,7 +58,7 @@ public class SessionRegistryImplTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityContext getSecurityContext() {
|
||||
public List<SecurityContext> getSecurityContexts() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user