diff --git a/spring-boot-project/spring-boot-autoconfigure/build.gradle b/spring-boot-project/spring-boot-autoconfigure/build.gradle index 456481a5ac..c5cfa8171c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/build.gradle +++ b/spring-boot-project/spring-boot-autoconfigure/build.gradle @@ -198,6 +198,7 @@ dependencies { optional("org.springframework.security:spring-security-oauth2-jose") optional("org.springframework.security:spring-security-oauth2-resource-server") optional("org.springframework.security:spring-security-rsocket") + optional("org.springframework.security:spring-security-messaging") optional("org.springframework.security:spring-security-saml2-service-provider") optional("org.springframework.security:spring-security-web") optional("org.springframework.session:spring-session-core") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfiguration.java index 69235ed362..06d20db59d 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,10 +18,12 @@ package org.springframework.boot.autoconfigure.security.rsocket; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.rsocket.RSocketMessageHandlerCustomizer; import org.springframework.boot.rsocket.server.RSocketServerCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.rsocket.EnableRSocketSecurity; +import org.springframework.security.messaging.handler.invocation.reactive.AuthenticationPrincipalArgumentResolver; import org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor; /** @@ -30,6 +32,7 @@ import org.springframework.security.rsocket.core.SecuritySocketAcceptorIntercept * * @author Madhura Bhave * @author Brian Clozel + * @author Guirong Hu * @since 2.2.0 */ @Configuration(proxyBeanMethods = false) @@ -42,4 +45,16 @@ public class RSocketSecurityAutoConfiguration { return (server) -> server.interceptors((registry) -> registry.forSocketAcceptor(interceptor)); } + @ConditionalOnClass(AuthenticationPrincipalArgumentResolver.class) + @Configuration(proxyBeanMethods = false) + static class RSocketSecurityMessageHandlerConfiguration { + + @Bean + RSocketMessageHandlerCustomizer springSecurityRSocketMessageHandler() { + return (messageHandler) -> messageHandler.getArgumentResolverConfigurer() + .addCustomResolver(new AuthenticationPrincipalArgumentResolver()); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfigurationTests.java index 8b6f2411dc..f4ea2bdc82 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/security/rsocket/RSocketSecurityAutoConfigurationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2020 the original author or authors. + * Copyright 2012-2022 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,17 +16,23 @@ package org.springframework.boot.autoconfigure.security.rsocket; +import java.util.List; + import io.rsocket.core.RSocketServer; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.autoconfigure.rsocket.RSocketMessageHandlerCustomizer; import org.springframework.boot.autoconfigure.rsocket.RSocketMessagingAutoConfiguration; import org.springframework.boot.autoconfigure.rsocket.RSocketStrategiesAutoConfiguration; import org.springframework.boot.autoconfigure.security.reactive.ReactiveUserDetailsServiceAutoConfiguration; import org.springframework.boot.rsocket.server.RSocketServerCustomizer; import org.springframework.boot.test.context.FilteredClassLoader; import org.springframework.boot.test.context.runner.ApplicationContextRunner; +import org.springframework.messaging.handler.invocation.reactive.HandlerMethodArgumentResolver; +import org.springframework.messaging.rsocket.annotation.support.RSocketMessageHandler; import org.springframework.security.config.annotation.rsocket.RSocketSecurity; +import org.springframework.security.messaging.handler.invocation.reactive.AuthenticationPrincipalArgumentResolver; import org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor; import static org.assertj.core.api.Assertions.assertThat; @@ -69,4 +75,19 @@ class RSocketSecurityAutoConfigurationTests { }); } + @Test + void autoConfigurationAddsCustomizerForMessageHandlerRSocketFactory() { + RSocketMessageHandler handler = new RSocketMessageHandler(); + this.contextRunner.run((context) -> { + RSocketMessageHandlerCustomizer customizer = context.getBean(RSocketMessageHandlerCustomizer.class); + customizer.customize(handler); + + List customResolvers = handler.getArgumentResolverConfigurer() + .getCustomResolvers(); + assertThat(customResolvers).isNotEmpty(); + assertThat(customResolvers) + .anyMatch((customResolver) -> customResolver instanceof AuthenticationPrincipalArgumentResolver); + }); + } + }