Skip to content

Commit 56b9bad

Browse files
evgeniychebanSteve Riesenberg
authored andcommitted
AnonymousAuthenticationFilter should cache its Supplier<SecurityContext>
Closes gh-11900
1 parent 5a55987 commit 56b9bad

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

web/src/main/java/org/springframework/security/web/authentication/AnonymousAuthenticationFilter.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.springframework.security.core.context.SecurityContextHolder;
3838
import org.springframework.security.core.context.SecurityContextHolderStrategy;
3939
import org.springframework.util.Assert;
40+
import org.springframework.util.function.SingletonSupplier;
4041
import org.springframework.web.filter.GenericFilterBean;
4142

4243
/**
@@ -45,6 +46,7 @@
4546
*
4647
* @author Ben Alex
4748
* @author Luke Taylor
49+
* @author Evgeniy Cheban
4850
*/
4951
public class AnonymousAuthenticationFilter extends GenericFilterBean implements InitializingBean {
5052

@@ -100,10 +102,10 @@ public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
100102

101103
private Supplier<SecurityContext> defaultWithAnonymous(HttpServletRequest request,
102104
Supplier<SecurityContext> currentDeferredContext) {
103-
return () -> {
105+
return SingletonSupplier.of(() -> {
104106
SecurityContext currentContext = currentDeferredContext.get();
105107
return defaultWithAnonymous(request, currentContext);
106-
};
108+
});
107109
}
108110

109111
private SecurityContext defaultWithAnonymous(HttpServletRequest request, SecurityContext currentContext) {

web/src/test/java/org/springframework/security/MockSecurityContextHolderStrategy.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,57 @@
1616

1717
package org.springframework.security;
1818

19+
import java.util.function.Supplier;
20+
1921
import org.springframework.security.core.Authentication;
2022
import org.springframework.security.core.context.SecurityContext;
2123
import org.springframework.security.core.context.SecurityContextHolderStrategy;
2224
import org.springframework.security.core.context.SecurityContextImpl;
2325

2426
public class MockSecurityContextHolderStrategy implements SecurityContextHolderStrategy {
2527

26-
private SecurityContext mock;
28+
private Supplier<SecurityContext> mock;
2729

2830
public MockSecurityContextHolderStrategy() {
2931

3032
}
3133

3234
public MockSecurityContextHolderStrategy(Authentication authentication) {
33-
this.mock = new SecurityContextImpl(authentication);
35+
this(() -> new SecurityContextImpl(authentication));
36+
}
37+
38+
public MockSecurityContextHolderStrategy(Supplier<SecurityContext> mock) {
39+
this.mock = mock;
3440
}
3541

3642
@Override
3743
public void clearContext() {
38-
this.mock = null;
44+
this.mock = () -> null;
3945
}
4046

4147
@Override
4248
public SecurityContext getContext() {
43-
return this.mock;
49+
return this.mock.get();
4450
}
4551

4652
@Override
4753
public void setContext(SecurityContext context) {
48-
this.mock = context;
54+
this.mock = () -> context;
4955
}
5056

5157
@Override
5258
public SecurityContext createEmptyContext() {
5359
return new SecurityContextImpl();
5460
}
5561

62+
@Override
63+
public Supplier<SecurityContext> getDeferredContext() {
64+
return this.mock;
65+
}
66+
67+
@Override
68+
public void setDeferredContext(Supplier<SecurityContext> deferredContext) {
69+
this.mock = deferredContext;
70+
}
71+
5672
}

web/src/test/java/org/springframework/security/web/authentication/AnonymousAuthenticationFilterTests.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232

3333
import org.springframework.mock.web.MockHttpServletRequest;
3434
import org.springframework.mock.web.MockHttpServletResponse;
35+
import org.springframework.security.MockSecurityContextHolderStrategy;
3536
import org.springframework.security.authentication.TestingAuthenticationToken;
3637
import org.springframework.security.core.Authentication;
3738
import org.springframework.security.core.authority.AuthorityUtils;
@@ -46,13 +47,15 @@
4647
import static org.mockito.BDDMockito.given;
4748
import static org.mockito.Mockito.mock;
4849
import static org.mockito.Mockito.never;
50+
import static org.mockito.Mockito.times;
4951
import static org.mockito.Mockito.verify;
5052

5153
/**
5254
* Tests {@link AnonymousAuthenticationFilter}.
5355
*
5456
* @author Ben Alex
5557
* @author Eddú Meléndez
58+
* @author Evgeniy Cheban
5659
*/
5760
public class AnonymousAuthenticationFilterTests {
5861

@@ -128,6 +131,25 @@ public void doFilterDoesNotGetContext() throws Exception {
128131
verify(originalSupplier, never()).get();
129132
}
130133

134+
@Test
135+
public void doFilterSetsSingletonSupplier() throws Exception {
136+
Supplier<SecurityContext> originalSupplier = mock(Supplier.class);
137+
Authentication originalAuth = new TestingAuthenticationToken("user", "password", "ROLE_A");
138+
SecurityContext originalContext = new SecurityContextImpl(originalAuth);
139+
SecurityContextHolderStrategy strategy = new MockSecurityContextHolderStrategy(originalSupplier);
140+
given(originalSupplier.get()).willReturn(originalContext);
141+
AnonymousAuthenticationFilter filter = new AnonymousAuthenticationFilter("qwerty", "anonymousUsername",
142+
AuthorityUtils.createAuthorityList("ROLE_ANONYMOUS"));
143+
filter.setSecurityContextHolderStrategy(strategy);
144+
filter.afterPropertiesSet();
145+
executeFilterInContainerSimulator(mock(FilterConfig.class), filter, new MockHttpServletRequest(),
146+
new MockHttpServletResponse(), new MockFilterChain(true));
147+
Supplier<SecurityContext> deferredContext = strategy.getDeferredContext();
148+
deferredContext.get();
149+
deferredContext.get();
150+
verify(originalSupplier, times(1)).get();
151+
}
152+
131153
private class MockFilterChain implements FilterChain {
132154

133155
private boolean expectToProceed;

0 commit comments

Comments
 (0)