|
35 | 35 | import org.springframework.security.access.PermissionEvaluator;
|
36 | 36 | import org.springframework.security.access.expression.SecurityExpressionHandler;
|
37 | 37 | import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
| 38 | +import org.springframework.security.authorization.AuthorizationDecision; |
38 | 39 | import org.springframework.security.authorization.AuthorizationManager;
|
| 40 | +import org.springframework.security.authorization.SingleResultAuthorizationManager; |
39 | 41 | import org.springframework.security.config.ObjectPostProcessor;
|
40 | 42 | import org.springframework.security.config.annotation.AbstractConfiguredSecurityBuilder;
|
41 | 43 | import org.springframework.security.config.annotation.SecurityBuilder;
|
|
58 | 60 | import org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler;
|
59 | 61 | import org.springframework.security.web.access.intercept.AuthorizationFilter;
|
60 | 62 | import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;
|
| 63 | +import org.springframework.security.web.access.intercept.RequestAuthorizationContext; |
| 64 | +import org.springframework.security.web.access.intercept.RequestMatcherDelegatingAuthorizationManager; |
61 | 65 | import org.springframework.security.web.debug.DebugFilter;
|
62 | 66 | import org.springframework.security.web.firewall.CompositeRequestRejectedHandler;
|
63 | 67 | import org.springframework.security.web.firewall.HttpFirewall;
|
64 | 68 | import org.springframework.security.web.firewall.HttpStatusRequestRejectedHandler;
|
65 | 69 | import org.springframework.security.web.firewall.ObservationMarkingRequestRejectedHandler;
|
66 | 70 | import org.springframework.security.web.firewall.RequestRejectedHandler;
|
67 | 71 | import org.springframework.security.web.firewall.StrictHttpFirewall;
|
| 72 | +import org.springframework.security.web.util.matcher.AnyRequestMatcher; |
68 | 73 | import org.springframework.security.web.util.matcher.RequestMatcher;
|
69 | 74 | import org.springframework.security.web.util.matcher.RequestMatcherEntry;
|
70 | 75 | import org.springframework.util.Assert;
|
@@ -230,8 +235,8 @@ public WebSecurity addSecurityFilterChainBuilder(
|
230 | 235 |
|
231 | 236 | /**
|
232 | 237 | * Set the {@link WebInvocationPrivilegeEvaluator} to be used. If this is not
|
233 |
| - * specified, then a {@link RequestMatcherDelegatingWebInvocationPrivilegeEvaluator} |
234 |
| - * will be created based on the list of {@link SecurityFilterChain}. |
| 238 | + * specified, then a {@link AuthorizationManagerWebInvocationPrivilegeEvaluator} will |
| 239 | + * be created based on the list of {@link SecurityFilterChain}. |
235 | 240 | * @param privilegeEvaluator the {@link WebInvocationPrivilegeEvaluator} to use
|
236 | 241 | * @return the {@link WebSecurity} for further customizations
|
237 | 242 | */
|
@@ -300,24 +305,33 @@ protected Filter performBuild() throws Exception {
|
300 | 305 | + ".addSecurityFilterChainBuilder directly");
|
301 | 306 | int chainSize = this.ignoredRequests.size() + this.securityFilterChainBuilders.size();
|
302 | 307 | List<SecurityFilterChain> securityFilterChains = new ArrayList<>(chainSize);
|
303 |
| - List<RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>>> requestMatcherPrivilegeEvaluatorsEntries = new ArrayList<>(); |
| 308 | + RequestMatcherDelegatingAuthorizationManager.Builder builder = RequestMatcherDelegatingAuthorizationManager |
| 309 | + .builder(); |
| 310 | + boolean mappings = false; |
304 | 311 | for (RequestMatcher ignoredRequest : this.ignoredRequests) {
|
305 | 312 | WebSecurity.this.logger.warn("You are asking Spring Security to ignore " + ignoredRequest
|
306 | 313 | + ". This is not recommended -- please use permitAll via HttpSecurity#authorizeHttpRequests instead.");
|
307 | 314 | SecurityFilterChain securityFilterChain = new DefaultSecurityFilterChain(ignoredRequest);
|
308 | 315 | securityFilterChains.add(securityFilterChain);
|
309 |
| - requestMatcherPrivilegeEvaluatorsEntries |
310 |
| - .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain)); |
| 316 | + builder.add(ignoredRequest, SingleResultAuthorizationManager.permitAll()); |
| 317 | + mappings = true; |
311 | 318 | }
|
312 | 319 | for (SecurityBuilder<? extends SecurityFilterChain> securityFilterChainBuilder : this.securityFilterChainBuilders) {
|
313 | 320 | SecurityFilterChain securityFilterChain = securityFilterChainBuilder.build();
|
314 | 321 | securityFilterChains.add(securityFilterChain);
|
315 |
| - requestMatcherPrivilegeEvaluatorsEntries |
316 |
| - .add(getRequestMatcherPrivilegeEvaluatorsEntry(securityFilterChain)); |
| 322 | + mappings = addAuthorizationManager(securityFilterChain, builder) || mappings; |
317 | 323 | }
|
318 | 324 | if (this.privilegeEvaluator == null) {
|
| 325 | + AuthorizationManager<HttpServletRequest> authorizationManager = mappings ? builder.build() |
| 326 | + : SingleResultAuthorizationManager.permitAll(); |
| 327 | + AuthorizationManagerWebInvocationPrivilegeEvaluator privilegeEvaluator = new AuthorizationManagerWebInvocationPrivilegeEvaluator( |
| 328 | + authorizationManager); |
| 329 | + privilegeEvaluator.setServletContext(this.servletContext); |
| 330 | + if (this.privilegeEvaluatorRequestTransformer != null) { |
| 331 | + privilegeEvaluator.setRequestTransformer(this.privilegeEvaluatorRequestTransformer); |
| 332 | + } |
319 | 333 | this.privilegeEvaluator = new RequestMatcherDelegatingWebInvocationPrivilegeEvaluator(
|
320 |
| - requestMatcherPrivilegeEvaluatorsEntries); |
| 334 | + List.of(new RequestMatcherEntry<>(AnyRequestMatcher.INSTANCE, List.of(privilegeEvaluator)))); |
321 | 335 | }
|
322 | 336 | FilterChainProxy filterChainProxy = new FilterChainProxy(securityFilterChains);
|
323 | 337 | if (this.httpFirewall != null) {
|
@@ -350,30 +364,32 @@ else if (!this.observationRegistry.isNoop()) {
|
350 | 364 | return result;
|
351 | 365 | }
|
352 | 366 |
|
353 |
| - private RequestMatcherEntry<List<WebInvocationPrivilegeEvaluator>> getRequestMatcherPrivilegeEvaluatorsEntry( |
354 |
| - SecurityFilterChain securityFilterChain) { |
355 |
| - List<WebInvocationPrivilegeEvaluator> privilegeEvaluators = new ArrayList<>(); |
| 367 | + private boolean addAuthorizationManager(SecurityFilterChain securityFilterChain, |
| 368 | + RequestMatcherDelegatingAuthorizationManager.Builder builder) { |
| 369 | + boolean mappings = false; |
356 | 370 | for (Filter filter : securityFilterChain.getFilters()) {
|
357 |
| - if (filter instanceof FilterSecurityInterceptor) { |
358 |
| - DefaultWebInvocationPrivilegeEvaluator defaultWebInvocationPrivilegeEvaluator = new DefaultWebInvocationPrivilegeEvaluator( |
359 |
| - (FilterSecurityInterceptor) filter); |
360 |
| - defaultWebInvocationPrivilegeEvaluator.setServletContext(this.servletContext); |
361 |
| - privilegeEvaluators.add(defaultWebInvocationPrivilegeEvaluator); |
| 371 | + if (filter instanceof FilterSecurityInterceptor securityInterceptor) { |
| 372 | + DefaultWebInvocationPrivilegeEvaluator privilegeEvaluator = new DefaultWebInvocationPrivilegeEvaluator( |
| 373 | + securityInterceptor); |
| 374 | + privilegeEvaluator.setServletContext(this.servletContext); |
| 375 | + AuthorizationManager<RequestAuthorizationContext> authorizationManager = (authentication, context) -> { |
| 376 | + HttpServletRequest request = context.getRequest(); |
| 377 | + boolean result = privilegeEvaluator.isAllowed(request.getContextPath(), request.getRequestURI(), |
| 378 | + request.getMethod(), authentication.get()); |
| 379 | + return new AuthorizationDecision(result); |
| 380 | + }; |
| 381 | + builder.add(securityFilterChain::matches, authorizationManager); |
| 382 | + mappings = true; |
362 | 383 | continue;
|
363 | 384 | }
|
364 |
| - if (filter instanceof AuthorizationFilter) { |
365 |
| - AuthorizationManager<HttpServletRequest> authorizationManager = ((AuthorizationFilter) filter) |
366 |
| - .getAuthorizationManager(); |
367 |
| - AuthorizationManagerWebInvocationPrivilegeEvaluator evaluator = new AuthorizationManagerWebInvocationPrivilegeEvaluator( |
368 |
| - authorizationManager); |
369 |
| - evaluator.setServletContext(this.servletContext); |
370 |
| - if (this.privilegeEvaluatorRequestTransformer != null) { |
371 |
| - evaluator.setRequestTransformer(this.privilegeEvaluatorRequestTransformer); |
372 |
| - } |
373 |
| - privilegeEvaluators.add(evaluator); |
| 385 | + if (filter instanceof AuthorizationFilter authorization) { |
| 386 | + AuthorizationManager<HttpServletRequest> authorizationManager = authorization.getAuthorizationManager(); |
| 387 | + builder.add(securityFilterChain::matches, |
| 388 | + (authentication, context) -> authorizationManager.check(authentication, context.getRequest())); |
| 389 | + mappings = true; |
374 | 390 | }
|
375 | 391 | }
|
376 |
| - return new RequestMatcherEntry<>(securityFilterChain::matches, privilegeEvaluators); |
| 392 | + return mappings; |
377 | 393 | }
|
378 | 394 |
|
379 | 395 | @Override
|
|
0 commit comments