1
0
mirror of synced 2026-08-05 09:47:05 +00:00

Add Support for @Transient SecurityContext

Closes gh-9995
This commit is contained in:
Rob Winch
2022-02-02 17:04:44 -06:00
parent f465403a99
commit 70fa8b1fdb
3 changed files with 112 additions and 4 deletions
@@ -232,11 +232,11 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
this.springSecurityContextKey = springSecurityContextKey;
}
private boolean isTransientAuthentication(Authentication authentication) {
if (authentication == null) {
private boolean isTransient(Object object) {
if (object == null) {
return false;
}
return AnnotationUtils.getAnnotation(authentication.getClass(), Transient.class) != null;
return AnnotationUtils.getAnnotation(object.getClass(), Transient.class) != null;
}
/**
@@ -329,8 +329,11 @@ public class HttpSessionSecurityContextRepository implements SecurityContextRepo
*/
@Override
protected void saveContext(SecurityContext context) {
if (isTransient(context)) {
return;
}
final Authentication authentication = context.getAuthentication();
if (isTransientAuthentication(authentication)) {
if (isTransient(authentication)) {
return;
}
HttpSession httpSession = this.request.getSession(false);
@@ -43,13 +43,16 @@ import org.springframework.mock.web.MockHttpSession;
import org.springframework.security.authentication.AbstractAuthenticationToken;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.TestAuthentication;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.Transient;
import org.springframework.security.core.authority.AuthorityUtils;
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.context.TransientSecurityContext;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
@@ -587,6 +590,68 @@ public class HttpSessionSecurityContextRepositoryTests {
assertThatIllegalStateException().isThrownBy(() -> repo.saveContext(context, request, response));
}
@Test
public void saveContextWhenTransientSecurityContextThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
SecurityContext context = repo.loadContext(holder);
SecurityContext transientSecurityContext = new TransientSecurityContext();
Authentication authentication = TestAuthentication.authenticatedUser();
transientSecurityContext.setAuthentication(authentication);
repo.saveContext(transientSecurityContext, holder.getRequest(), holder.getResponse());
MockHttpSession session = (MockHttpSession) request.getSession(false);
assertThat(session).isNull();
}
@Test
public void saveContextWhenTransientSecurityContextSubclassThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
SecurityContext context = repo.loadContext(holder);
SecurityContext transientSecurityContext = new TransientSecurityContext() {
};
Authentication authentication = TestAuthentication.authenticatedUser();
transientSecurityContext.setAuthentication(authentication);
repo.saveContext(transientSecurityContext, holder.getRequest(), holder.getResponse());
MockHttpSession session = (MockHttpSession) request.getSession(false);
assertThat(session).isNull();
}
@Test
public void saveContextWhenTransientSecurityContextAndSessionExistsThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
MockHttpServletRequest request = new MockHttpServletRequest();
request.getSession(); // ensure the session exists
MockHttpServletResponse response = new MockHttpServletResponse();
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
SecurityContext context = repo.loadContext(holder);
SecurityContext transientSecurityContext = new TransientSecurityContext();
Authentication authentication = TestAuthentication.authenticatedUser();
transientSecurityContext.setAuthentication(authentication);
repo.saveContext(transientSecurityContext, holder.getRequest(), holder.getResponse());
MockHttpSession session = (MockHttpSession) request.getSession(false);
assertThat(Collections.list(session.getAttributeNames())).isEmpty();
}
@Test
public void saveContextWhenTransientSecurityContextWithCustomAnnotationThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
HttpRequestResponseHolder holder = new HttpRequestResponseHolder(request, response);
SecurityContext context = repo.loadContext(holder);
SecurityContext transientSecurityContext = new TransientSecurityContext();
Authentication authentication = TestAuthentication.authenticatedUser();
transientSecurityContext.setAuthentication(authentication);
repo.saveContext(transientSecurityContext, holder.getRequest(), holder.getResponse());
MockHttpSession session = (MockHttpSession) request.getSession(false);
assertThat(session).isNull();
}
@Test
public void saveContextWhenTransientAuthenticationThenSkipped() {
HttpSessionSecurityContextRepository repo = new HttpSessionSecurityContextRepository();