1
0
mirror of synced 2026-08-04 17:27:13 +00:00

SEC-1695: Allow customization of the session key under which the SecurityContext is stored.

This commit is contained in:
Luke Taylor
2011-05-25 19:51:47 +01:00
parent 42e0e158b4
commit 6d04670f87
8 changed files with 108 additions and 65 deletions
@@ -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;
* &lt;/list&gt;
* &lt;/property&gt;
* </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);
}
}
}
@@ -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.
@@ -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();
@@ -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);
@@ -58,7 +58,7 @@ public class SessionRegistryImplTests {
}
@Override
public SecurityContext getSecurityContext() {
public List<SecurityContext> getSecurityContexts() {
return null;
}
});