1717package org .springframework .boot .actuate .autoconfigure .security .servlet ;
1818
1919import java .io .IOException ;
20- import java .util .Arrays ;
21- import java .util .Comparator ;
2220import java .util .List ;
23- import java .util .Map ;
24- import java .util .Optional ;
25- import java .util .concurrent .ConcurrentHashMap ;
2621import java .util .stream .Collectors ;
2722
28- import org .jetbrains .annotations .NotNull ;
2923import org .junit .jupiter .api .Test ;
3024
31- import org .springframework .beans .factory .annotation .AnnotatedBeanDefinition ;
32- import org .springframework .beans .factory .config .BeanDefinitionHolder ;
3325import org .springframework .boot .actuate .autoconfigure .endpoint .EndpointAutoConfiguration ;
3426import org .springframework .boot .actuate .autoconfigure .endpoint .web .WebEndpointAutoConfiguration ;
3527import org .springframework .boot .actuate .autoconfigure .env .EnvironmentEndpointAutoConfiguration ;
4436import org .springframework .boot .test .context .FilteredClassLoader ;
4537import org .springframework .boot .test .context .assertj .AssertableWebApplicationContext ;
4638import org .springframework .boot .test .context .runner .WebApplicationContextRunner ;
47- import org .springframework .context .ConfigurableApplicationContext ;
4839import org .springframework .context .annotation .Bean ;
4940import org .springframework .context .annotation .Configuration ;
50- import org .springframework .core .Ordered ;
51- import org .springframework .core .ResolvableType ;
52- import org .springframework .core .annotation .AnnotationAttributes ;
53- import org .springframework .core .annotation .AnnotationUtils ;
5441import org .springframework .core .annotation .Order ;
5542import org .springframework .http .HttpStatus ;
5643import org .springframework .mock .web .MockFilterChain ;
7158 * Tests for {@link ManagementWebSecurityAutoConfiguration}.
7259 *
7360 * @author Madhura Bhave
61+ * @author Hatef Palizgar
7462 */
7563class ManagementWebSecurityAutoConfigurationTests {
7664
@@ -139,7 +127,7 @@ void backOffIfCustomSecurityIsAdded() {
139127 @ Test
140128 void backsOffIfSecurityFilterChainBeanIsPresent () {
141129 this .contextRunner .withUserConfiguration (TestSecurityFilterChainConfig .class ).run ((context ) -> {
142- assertThat (context .getBeansOfType (SecurityFilterChain .class )).isNotEmpty ( );
130+ assertThat (context .getBeansOfType (SecurityFilterChain .class )).hasSize ( 1 );
143131 assertThat (context .containsBean ("testSecurityFilterChain" )).isTrue ();
144132 });
145133 }
@@ -166,26 +154,19 @@ void backOffIfSaml2RelyingPartyAutoConfigurationPresent() {
166154
167155 @ Test
168156 void backOffIfRemoteDevToolsSecurityFilterChainIsPresent () {
169- this .contextRunner .withUserConfiguration (TestSecurityFilterChainConfig .class ).run ((context ) -> {
170- List <String > beanNames = getOrderedBeanNames (context );
171-
172- assertThat (beanNames ).containsExactly ("testRemoteDevToolsSecurityFilterChain" , "testSecurityFilterChain" );
173- assertThat (context .getBeansOfType (SecurityFilterChain .class ).size ()).isEqualTo (2 );
157+ this .contextRunner .withUserConfiguration (TestRemoteDevToolsSecurityFilterChainConfig .class ).run ((context ) -> {
158+ SecurityFilterChain testSecurityFilterChain = context .getBean ("testSecurityFilterChain" ,
159+ SecurityFilterChain .class );
160+ SecurityFilterChain testRemoteDevToolsSecurityFilterChain = context
161+ .getBean ("testRemoteDevToolsSecurityFilterChain" , SecurityFilterChain .class );
162+ List <SecurityFilterChain > orderedSecurityFilterChains = context .getBeanProvider (SecurityFilterChain .class )
163+ .orderedStream ().collect (Collectors .toList ());
164+ assertThat (orderedSecurityFilterChains ).containsExactly (testRemoteDevToolsSecurityFilterChain ,
165+ testSecurityFilterChain );
174166 assertThat (context ).doesNotHaveBean (ManagementWebSecurityAutoConfiguration .class );
175- assertThat (context .containsBean ("testRemoteDevToolsSecurityFilterChain" )).isTrue ();
176167 });
177168 }
178169
179- @ NotNull
180- private List <String > getOrderedBeanNames (AssertableWebApplicationContext context ) {
181- return Arrays .stream (context .getBeanNamesForType (SecurityFilterChain .class ))
182- .map ((beanName ) -> Optional .of (context ).map (ConfigurableApplicationContext ::getBeanFactory )
183- .map ((beanFactory ) -> beanFactory .getBeanDefinition (beanName ))
184- .map ((beanDefinition ) -> new BeanDefinitionHolder (beanDefinition , beanName )).orElse (null ))
185- .sorted (OrderAnnotatedBeanDefinitionComparator .INSTANCE ).map (BeanDefinitionHolder ::getBeanName )
186- .collect (Collectors .toList ());
187- }
188-
189170 private HttpStatus getResponseStatus (AssertableWebApplicationContext context , String path )
190171 throws IOException , javax .servlet .ServletException {
191172 FilterChainProxy filterChainProxy = context .getBean (FilterChainProxy .class );
@@ -223,6 +204,11 @@ SecurityFilterChain testSecurityFilterChain(HttpSecurity http) throws Exception
223204 .build ();
224205 }
225206
207+ }
208+
209+ @ Configuration (proxyBeanMethods = false )
210+ static class TestRemoteDevToolsSecurityFilterChainConfig extends TestSecurityFilterChainConfig {
211+
226212 @ Bean
227213 @ Order (SecurityProperties .BASIC_AUTH_ORDER - 1 )
228214 SecurityFilterChain testRemoteDevToolsSecurityFilterChain (HttpSecurity http ) throws Exception {
@@ -232,48 +218,4 @@ SecurityFilterChain testRemoteDevToolsSecurityFilterChain(HttpSecurity http) thr
232218
233219 }
234220
235- static class OrderAnnotatedBeanDefinitionComparator implements Comparator <BeanDefinitionHolder > {
236-
237- static final OrderAnnotatedBeanDefinitionComparator INSTANCE = new OrderAnnotatedBeanDefinitionComparator ();
238-
239- private final Map <String , Integer > beanNameToOrder = new ConcurrentHashMap <>();
240-
241- @ Override
242- public int compare (BeanDefinitionHolder beanOne , BeanDefinitionHolder beanTwo ) {
243- return getOrder (beanOne ).compareTo (getOrder (beanTwo ));
244- }
245-
246- private Integer getOrder (BeanDefinitionHolder bean ) {
247- return this .beanNameToOrder .computeIfAbsent (bean .getBeanName (),
248- (beanName ) -> Optional .of (bean ).map (BeanDefinitionHolder ::getBeanDefinition )
249- .filter (AnnotatedBeanDefinition .class ::isInstance ).map (AnnotatedBeanDefinition .class ::cast )
250- .map (this ::getOrderAnnotationAttributesFromFactoryMethod ).map (this ::getOrder )
251- .orElse (Ordered .LOWEST_PRECEDENCE ));
252- }
253-
254- private Integer getOrder (AnnotationAttributes annotationAttributes ) {
255- return Optional .ofNullable (annotationAttributes )
256- .map ((it ) -> it .getOrDefault ("value" , Ordered .LOWEST_PRECEDENCE )).map (Integer .class ::cast )
257- .orElse (Ordered .LOWEST_PRECEDENCE );
258- }
259-
260- private AnnotationAttributes getOrderAnnotationAttributesFromFactoryMethod (
261- AnnotatedBeanDefinition beanDefinition ) {
262- return Optional .of (beanDefinition ).map (AnnotatedBeanDefinition ::getFactoryMethodMetadata )
263- .filter ((methodMetadata ) -> methodMetadata .isAnnotated (Order .class .getName ()))
264- .map ((methodMetadata ) -> methodMetadata .getAnnotationAttributes (Order .class .getName ()))
265- .map (AnnotationAttributes ::fromMap )
266- .orElseGet (() -> getOrderAnnotationAttributesFromBeanClass (beanDefinition ));
267- }
268-
269- private AnnotationAttributes getOrderAnnotationAttributesFromBeanClass (AnnotatedBeanDefinition beanDefinition ) {
270- return Optional .of (beanDefinition ).map (AnnotatedBeanDefinition ::getResolvableType )
271- .map (ResolvableType ::resolve ).filter ((beanType ) -> beanType .isAnnotationPresent (Order .class ))
272- .map ((beanType ) -> beanType .getAnnotation (Order .class ))
273- .map (AnnotationUtils ::getAnnotationAttributes ).map (AnnotationAttributes ::fromMap ).orElse (null );
274-
275- }
276-
277- }
278-
279221}
0 commit comments