Skip to content

Commit 484f35c

Browse files
committed
Add SecurityContextHolderStrategy Java Configuration for Messaging
Issue gh-11061
1 parent 1e498df commit 484f35c

File tree

2 files changed

+34
-2
lines changed

2 files changed

+34
-2
lines changed

config/src/main/java/org/springframework/security/config/annotation/web/socket/WebSocketMessageBrokerSecurityConfiguration.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
import org.springframework.messaging.support.ChannelInterceptor;
3333
import org.springframework.security.authorization.AuthorizationManager;
3434
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
35+
import org.springframework.security.core.context.SecurityContextHolder;
36+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
3537
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
3638
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
3739
import org.springframework.security.messaging.context.AuthenticationPrincipalArgumentResolver;
@@ -59,7 +61,10 @@ final class WebSocketMessageBrokerSecurityConfiguration
5961
private static final AuthorizationManager<Message<?>> ANY_MESSAGE_AUTHENTICATED = MessageMatcherDelegatingAuthorizationManager
6062
.builder().anyMessage().authenticated().build();
6163

62-
private final ChannelInterceptor securityContextChannelInterceptor = new SecurityContextChannelInterceptor();
64+
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
65+
.getContextHolderStrategy();
66+
67+
private final SecurityContextChannelInterceptor securityContextChannelInterceptor = new SecurityContextChannelInterceptor();
6368

6469
private final ChannelInterceptor csrfChannelInterceptor = new CsrfChannelInterceptor();
6570

@@ -74,17 +79,27 @@ final class WebSocketMessageBrokerSecurityConfiguration
7479

7580
@Override
7681
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
77-
argumentResolvers.add(new AuthenticationPrincipalArgumentResolver());
82+
AuthenticationPrincipalArgumentResolver resolver = new AuthenticationPrincipalArgumentResolver();
83+
resolver.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
84+
argumentResolvers.add(resolver);
7885
}
7986

8087
@Override
8188
public void configureClientInboundChannel(ChannelRegistration registration) {
8289
this.authorizationChannelInterceptor
8390
.setAuthorizationEventPublisher(new SpringAuthorizationEventPublisher(this.context));
91+
this.authorizationChannelInterceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
92+
this.securityContextChannelInterceptor.setSecurityContextHolderStrategy(this.securityContextHolderStrategy);
8493
registration.interceptors(this.securityContextChannelInterceptor, this.csrfChannelInterceptor,
8594
this.authorizationChannelInterceptor);
8695
}
8796

97+
@Autowired(required = false)
98+
void setSecurityContextHolderStrategy(SecurityContextHolderStrategy securityContextHolderStrategy) {
99+
Assert.notNull(securityContextHolderStrategy, "securityContextHolderStrategy cannot be null");
100+
this.securityContextHolderStrategy = securityContextHolderStrategy;
101+
}
102+
88103
@Autowired(required = false)
89104
void setAuthorizationManager(AuthorizationManager<Message<?>> authorizationManager) {
90105
this.authorizationChannelInterceptor = new AuthorizationChannelInterceptor(authorizationManager);

config/src/test/java/org/springframework/security/config/annotation/web/socket/WebSocketMessageBrokerSecurityConfigurationTests.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,11 @@
5454
import org.springframework.security.authentication.TestingAuthenticationToken;
5555
import org.springframework.security.authorization.AuthorizationDecision;
5656
import org.springframework.security.authorization.AuthorizationManager;
57+
import org.springframework.security.config.annotation.SecurityContextChangedListenerConfig;
5758
import org.springframework.security.config.annotation.web.messaging.MessageSecurityMetadataSourceRegistry;
5859
import org.springframework.security.core.Authentication;
5960
import org.springframework.security.core.annotation.AuthenticationPrincipal;
61+
import org.springframework.security.core.context.SecurityContextHolderStrategy;
6062
import org.springframework.security.messaging.access.intercept.AuthorizationChannelInterceptor;
6163
import org.springframework.security.messaging.access.intercept.MessageAuthorizationContext;
6264
import org.springframework.security.messaging.access.intercept.MessageMatcherDelegatingAuthorizationManager;
@@ -84,6 +86,8 @@
8486
import static org.assertj.core.api.Assertions.assertThat;
8587
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
8688
import static org.assertj.core.api.Assertions.fail;
89+
import static org.mockito.Mockito.atLeastOnce;
90+
import static org.mockito.Mockito.verify;
8791

8892
public class WebSocketMessageBrokerSecurityConfigurationTests {
8993

@@ -225,6 +229,18 @@ public void messagesConnectWebSocketUseCsrfTokenHandshakeInterceptor() throws Ex
225229
assertHandshake(request);
226230
}
227231

232+
@Test
233+
public void messagesContextWebSocketUseSecurityContextHolderStrategy() {
234+
loadConfig(WebSocketSecurityConfig.class, SecurityContextChangedListenerConfig.class);
235+
SimpMessageHeaderAccessor headers = SimpMessageHeaderAccessor.create(SimpMessageType.CONNECT);
236+
headers.setNativeHeader(this.token.getHeaderName(), this.token.getToken());
237+
Message<?> message = message(headers, "/authenticated");
238+
headers.getSessionAttributes().put(CsrfToken.class.getName(), this.token);
239+
MessageChannel messageChannel = clientInboundChannel();
240+
messageChannel.send(message);
241+
verify(this.context.getBean(SecurityContextHolderStrategy.class), atLeastOnce()).getContext();
242+
}
243+
228244
@Test
229245
public void msmsRegistryCustomPatternMatcher() {
230246
loadConfig(MsmsRegistryCustomPatternMatcherConfig.class);
@@ -691,6 +707,7 @@ AuthorizationManager<Message<?>> authorizationManager(
691707
// @formatter:off
692708
messages
693709
.simpDestMatchers("/permitAll/**").permitAll()
710+
.simpDestMatchers("/authenticated/**").authenticated()
694711
.anyMessage().denyAll();
695712
// @formatter:on
696713
return messages.build();

0 commit comments

Comments
 (0)