17
17
package org .springframework .boot .actuate .autoconfigure .security .servlet ;
18
18
19
19
import java .io .IOException ;
20
- import java .util .Arrays ;
21
- import java .util .Comparator ;
22
20
import java .util .List ;
23
- import java .util .Map ;
24
- import java .util .Optional ;
25
- import java .util .concurrent .ConcurrentHashMap ;
26
21
import java .util .stream .Collectors ;
27
22
28
- import org .jetbrains .annotations .NotNull ;
29
23
import org .junit .jupiter .api .Test ;
30
24
31
- import org .springframework .beans .factory .annotation .AnnotatedBeanDefinition ;
32
- import org .springframework .beans .factory .config .BeanDefinitionHolder ;
33
25
import org .springframework .boot .actuate .autoconfigure .endpoint .EndpointAutoConfiguration ;
34
26
import org .springframework .boot .actuate .autoconfigure .endpoint .web .WebEndpointAutoConfiguration ;
35
27
import org .springframework .boot .actuate .autoconfigure .env .EnvironmentEndpointAutoConfiguration ;
44
36
import org .springframework .boot .test .context .FilteredClassLoader ;
45
37
import org .springframework .boot .test .context .assertj .AssertableWebApplicationContext ;
46
38
import org .springframework .boot .test .context .runner .WebApplicationContextRunner ;
47
- import org .springframework .context .ConfigurableApplicationContext ;
48
39
import org .springframework .context .annotation .Bean ;
49
40
import 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 ;
54
41
import org .springframework .core .annotation .Order ;
55
42
import org .springframework .http .HttpStatus ;
56
43
import org .springframework .mock .web .MockFilterChain ;
71
58
* Tests for {@link ManagementWebSecurityAutoConfiguration}.
72
59
*
73
60
* @author Madhura Bhave
61
+ * @author Hatef Palizgar
74
62
*/
75
63
class ManagementWebSecurityAutoConfigurationTests {
76
64
@@ -139,7 +127,7 @@ void backOffIfCustomSecurityIsAdded() {
139
127
@ Test
140
128
void backsOffIfSecurityFilterChainBeanIsPresent () {
141
129
this .contextRunner .withUserConfiguration (TestSecurityFilterChainConfig .class ).run ((context ) -> {
142
- assertThat (context .getBeansOfType (SecurityFilterChain .class )).isNotEmpty ( );
130
+ assertThat (context .getBeansOfType (SecurityFilterChain .class )).hasSize ( 1 );
143
131
assertThat (context .containsBean ("testSecurityFilterChain" )).isTrue ();
144
132
});
145
133
}
@@ -166,26 +154,19 @@ void backOffIfSaml2RelyingPartyAutoConfigurationPresent() {
166
154
167
155
@ Test
168
156
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 );
174
166
assertThat (context ).doesNotHaveBean (ManagementWebSecurityAutoConfiguration .class );
175
- assertThat (context .containsBean ("testRemoteDevToolsSecurityFilterChain" )).isTrue ();
176
167
});
177
168
}
178
169
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
-
189
170
private HttpStatus getResponseStatus (AssertableWebApplicationContext context , String path )
190
171
throws IOException , javax .servlet .ServletException {
191
172
FilterChainProxy filterChainProxy = context .getBean (FilterChainProxy .class );
@@ -223,6 +204,11 @@ SecurityFilterChain testSecurityFilterChain(HttpSecurity http) throws Exception
223
204
.build ();
224
205
}
225
206
207
+ }
208
+
209
+ @ Configuration (proxyBeanMethods = false )
210
+ static class TestRemoteDevToolsSecurityFilterChainConfig extends TestSecurityFilterChainConfig {
211
+
226
212
@ Bean
227
213
@ Order (SecurityProperties .BASIC_AUTH_ORDER - 1 )
228
214
SecurityFilterChain testRemoteDevToolsSecurityFilterChain (HttpSecurity http ) throws Exception {
@@ -232,48 +218,4 @@ SecurityFilterChain testRemoteDevToolsSecurityFilterChain(HttpSecurity http) thr
232
218
233
219
}
234
220
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
-
279
221
}
0 commit comments