Explorar o código

Replace bean method calls with injection

This is so that our configuration classes do not rely on CGLIB to proxy bean methods.

Fixes gh-6818
Eleftheria Stein %!s(int64=6) %!d(string=hai) anos
pai
achega
06d3b60947
Modificáronse 12 ficheiros con 337 adicións e 36 borrados
  1. 2 3
      config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java
  2. 8 12
      config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java
  3. 10 5
      config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java
  4. 6 6
      config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java
  5. 19 4
      config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java
  6. 18 1
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java
  7. 3 3
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java
  8. 20 0
      config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java
  9. 50 1
      config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java
  10. 58 0
      config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTest.java
  11. 58 0
      config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java
  12. 85 1
      config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java

+ 2 - 3
config/src/main/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -107,8 +107,7 @@ public class AuthenticationConfiguration {
 		if (this.authenticationManagerInitialized) {
 			return this.authenticationManager;
 		}
-		AuthenticationManagerBuilder authBuilder = authenticationManagerBuilder(
-				this.objectPostProcessor, this.applicationContext);
+		AuthenticationManagerBuilder authBuilder = this.applicationContext.getBean(AuthenticationManagerBuilder.class);
 		if (this.buildingAuthenticationManager.getAndSet(true)) {
 			return new AuthenticationManagerDelegator(authBuilder);
 		}

+ 8 - 12
config/src/main/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfiguration.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -29,10 +29,7 @@ import org.springframework.beans.factory.BeanFactoryAware;
 import org.springframework.beans.factory.NoSuchBeanDefinitionException;
 import org.springframework.beans.factory.SmartInitializingSingleton;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.AdviceMode;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.ImportAware;
+import org.springframework.context.annotation.*;
 import org.springframework.core.annotation.AnnotationAttributes;
 import org.springframework.core.annotation.AnnotationUtils;
 import org.springframework.core.type.AnnotationMetadata;
@@ -110,7 +107,6 @@ public class GlobalMethodSecurityConfiguration
 	 * <li>{@link #accessDecisionManager()}</li>
 	 * <li>{@link #afterInvocationManager()}</li>
 	 * <li>{@link #authenticationManager()}</li>
-	 * <li>{@link #methodSecurityMetadataSource()}</li>
 	 * <li>{@link #runAsManager()}</li>
 	 *
 	 * </ul>
@@ -119,19 +115,19 @@ public class GlobalMethodSecurityConfiguration
 	 * Subclasses can override this method to provide a different
 	 * {@link MethodInterceptor}.
 	 * </p>
+	 * @param methodSecurityMetadataSource the default {@link MethodSecurityMetadataSource}.
 	 *
 	 * @return the {@link MethodInterceptor}.
-	 * @throws Exception
 	 */
 	@Bean
-	public MethodInterceptor methodSecurityInterceptor() throws Exception {
+	public MethodInterceptor methodSecurityInterceptor(MethodSecurityMetadataSource methodSecurityMetadataSource) {
 		this.methodSecurityInterceptor = isAspectJ()
 				? new AspectJMethodSecurityInterceptor()
 				: new MethodSecurityInterceptor();
 		methodSecurityInterceptor.setAccessDecisionManager(accessDecisionManager());
 		methodSecurityInterceptor.setAfterInvocationManager(afterInvocationManager());
 		methodSecurityInterceptor
-				.setSecurityMetadataSource(methodSecurityMetadataSource());
+				.setSecurityMetadataSource(methodSecurityMetadataSource);
 		RunAsManager runAsManager = runAsManager();
 		if (runAsManager != null) {
 			methodSecurityInterceptor.setRunAsManager(runAsManager);
@@ -197,8 +193,8 @@ public class GlobalMethodSecurityConfiguration
 
 	/**
 	 * Provide a custom {@link AfterInvocationManager} for the default implementation of
-	 * {@link #methodSecurityInterceptor()}. The default is null if pre post is not
-	 * enabled. Otherwise, it returns a {@link AfterInvocationProviderManager}.
+	 * {@link #methodSecurityInterceptor(MethodSecurityMetadataSource)}. The default is null
+	 * if pre post is not enabled. Otherwise, it returns a {@link AfterInvocationProviderManager}.
 	 *
 	 * <p>
 	 * Subclasses should override this method to provide a custom
@@ -224,7 +220,7 @@ public class GlobalMethodSecurityConfiguration
 
 	/**
 	 * Provide a custom {@link RunAsManager} for the default implementation of
-	 * {@link #methodSecurityInterceptor()}. The default is null.
+	 * {@link #methodSecurityInterceptor(MethodSecurityMetadataSource)}. The default is null.
 	 *
 	 * @return the {@link RunAsManager} to use
 	 */

+ 10 - 5
config/src/main/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfiguration.java

@@ -43,7 +43,7 @@ import org.springframework.web.reactive.result.method.annotation.ArgumentResolve
  * @since 5.0
  */
 @Configuration
-class ServerHttpSecurityConfiguration implements WebFluxConfigurer {
+class ServerHttpSecurityConfiguration {
 	private static final String BEAN_NAME_PREFIX = "org.springframework.security.config.annotation.web.reactive.HttpSecurityConfiguration.";
 	private static final String HTTPSECURITY_BEAN_NAME = BEAN_NAME_PREFIX + "httpSecurity";
 
@@ -85,9 +85,15 @@ class ServerHttpSecurityConfiguration implements WebFluxConfigurer {
 		this.userDetailsPasswordService = userDetailsPasswordService;
 	}
 
-	@Override
-	public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
-		configurer.addCustomResolver(authenticationPrincipalArgumentResolver());
+	@Bean
+	public WebFluxConfigurer authenticationPrincipalArgumentResolverConfigurer(
+			AuthenticationPrincipalArgumentResolver authenticationPrincipalArgumentResolver) {
+		return new WebFluxConfigurer() {
+			@Override
+			public void configureArgumentResolvers(ArgumentResolverConfigurer configurer) {
+				configurer.addCustomResolver(authenticationPrincipalArgumentResolver);
+			}
+		};
 	}
 
 	@Bean
@@ -110,7 +116,6 @@ class ServerHttpSecurityConfiguration implements WebFluxConfigurer {
 		return resolver;
 	}
 
-
 	@Bean(HTTPSECURITY_BEAN_NAME)
 	@Scope("prototype")
 	public ServerHttpSecurity httpSecurity() {

+ 6 - 6
config/src/main/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurer.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -103,10 +103,10 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends
 
 	@Override
 	public final void configureClientInboundChannel(ChannelRegistration registration) {
-		ChannelSecurityInterceptor inboundChannelSecurity = inboundChannelSecurity();
-		registration.setInterceptors(securityContextChannelInterceptor());
+		ChannelSecurityInterceptor inboundChannelSecurity = context.getBean(ChannelSecurityInterceptor.class);
+		registration.setInterceptors(context.getBean(SecurityContextChannelInterceptor.class));
 		if (!sameOriginDisabled()) {
-			registration.setInterceptors(csrfChannelInterceptor());
+			registration.setInterceptors(context.getBean(CsrfChannelInterceptor.class));
 		}
 		if (inboundRegistry.containsMapping()) {
 			registration.setInterceptors(inboundChannelSecurity);
@@ -153,9 +153,9 @@ public abstract class AbstractSecurityWebSocketMessageBrokerConfigurer extends
 	}
 
 	@Bean
-	public ChannelSecurityInterceptor inboundChannelSecurity() {
+	public ChannelSecurityInterceptor inboundChannelSecurity(MessageSecurityMetadataSource messageSecurityMetadataSource) {
 		ChannelSecurityInterceptor channelSecurityInterceptor = new ChannelSecurityInterceptor(
-				inboundMessageSecurityMetadataSource());
+				messageSecurityMetadataSource);
 		MessageExpressionVoter<Object> voter = new MessageExpressionVoter<>();
 		voter.setExpressionHandler(getMessageExpressionHandler());
 

+ 19 - 4
config/src/test/java/org/springframework/security/config/annotation/authentication/configuration/AuthenticationConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -34,6 +34,7 @@ import org.springframework.security.authentication.TestAuthentication;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
 import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.AlreadyBuiltException;
 import org.springframework.security.config.annotation.ObjectPostProcessor;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
 import org.springframework.security.config.annotation.configuration.ObjectPostProcessorConfiguration;
@@ -64,9 +65,7 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.startsWith;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 public class AuthenticationConfigurationTests {
 
@@ -530,4 +529,20 @@ public class AuthenticationConfigurationTests {
 		}
 
 	}
+
+	@Test
+	public void getAuthenticationManagerWhenAuthenticationConfigurationSubclassedThenBuildsUsingBean()
+			throws Exception {
+		this.spring.register(AuthenticationConfigurationSubclass.class).autowire();
+		AuthenticationManagerBuilder ap = this.spring.getContext().getBean(AuthenticationManagerBuilder.class);
+
+		this.spring.getContext().getBean(AuthenticationConfiguration.class).getAuthenticationManager();
+
+		assertThatThrownBy(ap::build)
+				.isInstanceOf(AlreadyBuiltException.class);
+	}
+
+	@Configuration(proxyBeanMethods = false)
+	static class AuthenticationConfigurationSubclass extends AuthenticationConfiguration {
+	}
 }

+ 18 - 1
config/src/test/java/org/springframework/security/config/annotation/method/configuration/GlobalMethodSecurityConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -20,6 +20,7 @@ import java.util.HashMap;
 import java.util.Map;
 import javax.sql.DataSource;
 
+import org.aopalliance.intercept.MethodInterceptor;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.ExpectedException;
@@ -553,4 +554,20 @@ public class GlobalMethodSecurityConfigurationTests {
 			public void emptyPrefixRoleUser() {}
 		}
 	}
+
+	@Test
+	public void methodSecurityInterceptorUsesMetadataSourceBeanWhenProxyingDisabled() {
+		this.spring.register(CustomMetadataSourceProxylessConfig.class).autowire();
+		MethodSecurityInterceptor methodInterceptor =
+				(MethodSecurityInterceptor) this.spring.getContext().getBean(MethodInterceptor.class);
+		MethodSecurityMetadataSource methodSecurityMetadataSource =
+				this.spring.getContext().getBean(MethodSecurityMetadataSource.class);
+
+		assertThat(methodInterceptor.getSecurityMetadataSource()).isSameAs(methodSecurityMetadataSource);
+	}
+
+	@EnableGlobalMethodSecurity(prePostEnabled = true)
+	@Configuration(proxyBeanMethods = false)
+	public static class CustomMetadataSourceProxylessConfig extends GlobalMethodSecurityConfiguration {
+	}
 }

+ 3 - 3
config/src/test/java/org/springframework/security/config/annotation/method/configuration/NamespaceGlobalMethodSecurityTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -163,8 +163,8 @@ public class NamespaceGlobalMethodSecurityTests {
 	public static class CustomAuthenticationConfig extends GlobalMethodSecurityConfiguration {
 
 		@Override
-		public MethodInterceptor methodSecurityInterceptor() throws Exception {
-			MethodInterceptor interceptor = super.methodSecurityInterceptor();
+		public MethodInterceptor methodSecurityInterceptor(MethodSecurityMetadataSource methodSecurityMetadataSource) {
+			MethodInterceptor interceptor = super.methodSecurityInterceptor(methodSecurityMetadataSource);
 			((MethodSecurityInterceptor) interceptor).setAlwaysReauthenticate(true);
 			return interceptor;
 		}

+ 20 - 0
config/src/test/java/org/springframework/security/config/annotation/method/configuration/ReactiveMethodSecurityConfigurationTests.java

@@ -88,4 +88,24 @@ public class ReactiveMethodSecurityConfigurationTests {
 		}
 	}
 
+	@Test
+	public void rolePrefixWithGrantedAuthorityDefaultsAndSubclassWithProxyingDisabled() {
+		this.spring.register(SubclassConfig.class).autowire();
+
+		TestingAuthenticationToken authentication = new TestingAuthenticationToken(
+				"principal", "credential", "ROLE_ABC");
+		MockMethodInvocation methodInvocation = mock(MockMethodInvocation.class);
+
+		EvaluationContext context = this.methodSecurityExpressionHandler
+				.createEvaluationContext(authentication, methodInvocation);
+		SecurityExpressionRoot root = (SecurityExpressionRoot) context.getRootObject()
+				.getValue();
+
+		assertThat(root.hasRole("ROLE_ABC")).isTrue();
+		assertThat(root.hasRole("ABC")).isTrue();
+	}
+
+	@Configuration(proxyBeanMethods = false)
+	static class SubclassConfig extends ReactiveMethodSecurityConfiguration {
+	}
 }

+ 50 - 1
config/src/test/java/org/springframework/security/config/annotation/web/configuration/WebSecurityConfigurationTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2018 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -34,6 +34,7 @@ import org.springframework.security.access.expression.AbstractSecurityExpression
 import org.springframework.security.access.expression.SecurityExpressionHandler;
 import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.authentication.configuration.EnableGlobalAuthentication;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.builders.WebSecurity;
 import org.springframework.security.config.test.SpringTestRule;
@@ -403,4 +404,52 @@ public class WebSecurityConfigurationTests {
 		Method method = ClassUtils.getMethod(WebSecurityConfiguration.class, "delegatingApplicationListener", null);
 		assertThat(Modifier.isStatic(method.getModifiers())).isTrue();
 	}
+
+	@Test
+	public void loadConfigWhenProxyingDisabledAndSubclassThenFilterChainsCreated() {
+		this.spring.register(GlobalAuthenticationWebSecurityConfigurerAdaptersConfig.class, SubclassConfig.class).autowire();
+
+		FilterChainProxy filterChainProxy = this.spring.getContext().getBean(FilterChainProxy.class);
+		List<SecurityFilterChain> filterChains = filterChainProxy.getFilterChains();
+
+		assertThat(filterChains).hasSize(4);
+	}
+
+	@Configuration(proxyBeanMethods = false)
+	static class SubclassConfig extends WebSecurityConfiguration {
+	}
+
+	@Import(AuthenticationTestConfiguration.class)
+	@EnableGlobalAuthentication
+	static class GlobalAuthenticationWebSecurityConfigurerAdaptersConfig {
+		@Configuration
+		@Order(1)
+		static class WebConfigurer1 extends WebSecurityConfigurerAdapter {
+			@Override
+			public void configure(WebSecurity web)	throws Exception {
+				web
+						.ignoring()
+						.antMatchers("/ignore1", "/ignore2");
+			}
+
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+						.antMatcher("/anonymous/**")
+						.authorizeRequests()
+						.anyRequest().anonymous();
+			}
+		}
+
+		@Configuration
+		static class WebConfigurer2 extends WebSecurityConfigurerAdapter {
+
+			@Override
+			protected void configure(HttpSecurity http) throws Exception {
+				http
+						.authorizeRequests()
+						.anyRequest().authenticated();
+			}
+		}
+	}
 }

+ 58 - 0
config/src/test/java/org/springframework/security/config/annotation/web/reactive/ServerHttpSecurityConfigurationTest.java

@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2019 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.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.config.annotation.web.reactive;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
+import org.springframework.security.config.web.server.ServerHttpSecurity;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link ServerHttpSecurityConfiguration}.
+ *
+ * @author Eleftheria Stein
+ */
+public class ServerHttpSecurityConfigurationTest {
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Test
+	public void loadConfigWhenReactiveUserDetailsServiceConfiguredThenServerHttpSecurityExists() {
+		this.spring.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
+				WebFluxSecurityConfiguration.class).autowire();
+		ServerHttpSecurity serverHttpSecurity = this.spring.getContext().getBean(ServerHttpSecurity.class);
+
+		assertThat(serverHttpSecurity).isNotNull();
+	}
+
+	@Test
+	public void loadConfigWhenProxyingDisabledAndSubclassThenServerHttpSecurityExists() {
+		this.spring.register(SubclassConfig.class, ReactiveAuthenticationTestConfiguration.class,
+				WebFluxSecurityConfiguration.class).autowire();
+		ServerHttpSecurity serverHttpSecurity = this.spring.getContext().getBean(ServerHttpSecurity.class);
+
+		assertThat(serverHttpSecurity).isNotNull();
+	}
+
+	@Configuration(proxyBeanMethods = false)
+	static class SubclassConfig extends ServerHttpSecurityConfiguration {
+	}
+}

+ 58 - 0
config/src/test/java/org/springframework/security/config/annotation/web/reactive/WebFluxSecurityConfigurationTests.java

@@ -0,0 +1,58 @@
+/*
+ * Copyright 2002-2019 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.
+ * You may obtain a copy of the License at
+ *
+ *      https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.security.config.annotation.web.reactive;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.security.config.users.ReactiveAuthenticationTestConfiguration;
+import org.springframework.security.web.server.WebFilterChainProxy;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Tests for {@link WebFluxSecurityConfiguration}.
+ *
+ * @author Eleftheria Stein
+ */
+public class WebFluxSecurityConfigurationTests {
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Test
+	public void loadConfigWhenReactiveUserDetailsServiceConfiguredThenWebFilterChainProxyExists() {
+		this.spring.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
+				WebFluxSecurityConfiguration.class).autowire();
+		WebFilterChainProxy webFilterChainProxy = this.spring.getContext().getBean(WebFilterChainProxy.class);
+
+		assertThat(webFilterChainProxy).isNotNull();
+	}
+
+	@Test
+	public void loadConfigWhenProxyingDisabledAndSubclassThenWebFilterChainProxyExists() {
+		this.spring.register(ServerHttpSecurityConfiguration.class, ReactiveAuthenticationTestConfiguration.class,
+				WebFluxSecurityConfigurationTests.SubclassConfig.class).autowire();
+		WebFilterChainProxy webFilterChainProxy = this.spring.getContext().getBean(WebFilterChainProxy.class);
+
+		assertThat(webFilterChainProxy).isNotNull();
+	}
+
+	@Configuration(proxyBeanMethods = false)
+	static class SubclassConfig extends WebFluxSecurityConfiguration {
+	}
+}

+ 85 - 1
config/src/test/java/org/springframework/security/config/annotation/web/socket/AbstractSecurityWebSocketMessageBrokerConfigurerTests.java

@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2016 the original author or authors.
+ * Copyright 2002-2019 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.
@@ -26,6 +26,8 @@ import javax.servlet.http.HttpServletRequest;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Import;
@@ -40,6 +42,7 @@ import org.springframework.messaging.handler.invocation.HandlerMethodArgumentRes
 import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
 import org.springframework.messaging.simp.SimpMessageType;
 import org.springframework.messaging.simp.config.MessageBrokerRegistry;
+import org.springframework.messaging.support.AbstractMessageChannel;
 import org.springframework.messaging.support.GenericMessage;
 import org.springframework.mock.web.MockHttpServletRequest;
 import org.springframework.mock.web.MockHttpServletResponse;
@@ -53,6 +56,10 @@ import org.springframework.security.core.Authentication;
 import org.springframework.security.core.annotation.AuthenticationPrincipal;
 import org.springframework.security.messaging.access.expression.DefaultMessageSecurityExpressionHandler;
 import org.springframework.security.messaging.access.expression.MessageSecurityExpressionRoot;
+import org.springframework.security.messaging.access.intercept.ChannelSecurityInterceptor;
+import org.springframework.security.messaging.access.intercept.MessageSecurityMetadataSource;
+import org.springframework.security.messaging.context.SecurityContextChannelInterceptor;
+import org.springframework.security.messaging.web.csrf.CsrfChannelInterceptor;
 import org.springframework.security.web.csrf.CsrfToken;
 import org.springframework.security.web.csrf.DefaultCsrfToken;
 import org.springframework.security.web.csrf.MissingCsrfTokenException;
@@ -199,6 +206,16 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		messageChannel.send(message);
 	}
 
+	@Test
+	public void csrfProtectionDefinedByBean() {
+		loadConfig(SockJsProxylessSecurityConfig.class);
+
+		MessageChannel messageChannel = clientInboundChannel();
+		CsrfChannelInterceptor csrfChannelInterceptor = context.getBean(CsrfChannelInterceptor.class);
+
+		assertThat(((AbstractMessageChannel) messageChannel).getInterceptors()).contains(csrfChannelInterceptor);
+	}
+
 	@Test
 	public void messagesConnectUseCsrfTokenHandshakeInterceptor() throws Exception {
 
@@ -421,6 +438,41 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		}
 	}
 
+	@Test
+	public void channelSecurityInterceptorUsesMetadataSourceBeanWhenProxyingDisabled() {
+
+		loadConfig(SockJsProxylessSecurityConfig.class);
+
+		ChannelSecurityInterceptor channelSecurityInterceptor = context.getBean(ChannelSecurityInterceptor.class);
+		MessageSecurityMetadataSource messageSecurityMetadataSource =
+				context.getBean(MessageSecurityMetadataSource.class);
+
+		assertThat(channelSecurityInterceptor.obtainSecurityMetadataSource()).isSameAs(messageSecurityMetadataSource);
+	}
+
+	@Test
+	public void securityContextChannelInterceptorDefinedByBean() {
+		loadConfig(SockJsProxylessSecurityConfig.class);
+
+		MessageChannel messageChannel = clientInboundChannel();
+		SecurityContextChannelInterceptor securityContextChannelInterceptor =
+				context.getBean(SecurityContextChannelInterceptor.class);
+
+		assertThat(((AbstractMessageChannel) messageChannel).getInterceptors())
+				.contains(securityContextChannelInterceptor);
+	}
+
+	@Test
+	public void inboundChannelSecurityDefinedByBean() {
+		loadConfig(SockJsProxylessSecurityConfig.class);
+
+		MessageChannel messageChannel = clientInboundChannel();
+		ChannelSecurityInterceptor inboundChannelSecurity = context.getBean(ChannelSecurityInterceptor.class);
+
+		assertThat(((AbstractMessageChannel) messageChannel).getInterceptors())
+				.contains(inboundChannelSecurity);
+	}
+
 	@Configuration
 	@EnableWebSocketMessageBroker
 	@Import(SyncExecutorConfig.class)
@@ -706,6 +758,38 @@ public class AbstractSecurityWebSocketMessageBrokerConfigurerTests {
 		}
 	}
 
+	@Configuration(proxyBeanMethods = false)
+	@EnableWebSocketMessageBroker
+	@Import(SyncExecutorConfig.class)
+	static class SockJsProxylessSecurityConfig extends
+			AbstractSecurityWebSocketMessageBrokerConfigurer {
+		private ApplicationContext context;
+
+		public void registerStompEndpoints(StompEndpointRegistry registry) {
+			registry.addEndpoint("/chat")
+					.setHandshakeHandler(context.getBean(TestHandshakeHandler.class))
+					.withSockJS().setInterceptors(new HttpSessionHandshakeInterceptor());
+		}
+
+		@Autowired
+		public void setContext(ApplicationContext context) {
+			this.context = context;
+		}
+
+		// @formatter:off
+		@Override
+		protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
+			messages
+					.anyMessage().denyAll();
+		}
+		// @formatter:on
+
+		@Bean
+		public TestHandshakeHandler testHandshakeHandler() {
+			return new TestHandshakeHandler();
+		}
+	}
+
 	@Configuration
 	static class SyncExecutorConfig {
 		@Bean