|
16 | 16 |
|
17 | 17 | package org.springframework.security.config.annotation.method.configuration;
|
18 | 18 |
|
| 19 | +import java.util.Collection; |
| 20 | +import java.util.Map; |
| 21 | +import java.util.concurrent.ConcurrentHashMap; |
19 | 22 | import java.util.function.Supplier;
|
20 | 23 |
|
21 | 24 | import org.aopalliance.intercept.MethodInterceptor;
|
22 | 25 | import org.aopalliance.intercept.MethodInvocation;
|
23 |
| - |
| 26 | +import org.jspecify.annotations.Nullable; |
24 | 27 | import org.springframework.aop.Pointcut;
|
25 | 28 | import org.springframework.aop.framework.AopInfrastructureBean;
|
26 | 29 | import org.springframework.beans.factory.ObjectProvider;
|
|
36 | 39 | import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
|
37 | 40 | import org.springframework.security.authorization.AuthorizationEventPublisher;
|
38 | 41 | import org.springframework.security.authorization.AuthorizationManager;
|
| 42 | +import org.springframework.security.authorization.AuthorizationManagerFactory; |
| 43 | +import org.springframework.security.authorization.AuthorizationResult; |
39 | 44 | import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
|
40 | 45 | import org.springframework.security.authorization.method.SecuredAuthorizationManager;
|
41 | 46 | import org.springframework.security.config.ObjectPostProcessor;
|
| 47 | +import org.springframework.security.core.Authentication; |
42 | 48 | import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
43 | 49 |
|
44 | 50 | /**
|
@@ -101,4 +107,38 @@ void setEventPublisher(AuthorizationEventPublisher eventPublisher) {
|
101 | 107 | this.methodInterceptor.setAuthorizationEventPublisher(eventPublisher);
|
102 | 108 | }
|
103 | 109 |
|
| 110 | + @Autowired(required = false) |
| 111 | + void setAuthorizationManagerFactory(AuthorizationManagerFactory<Collection<String>> authorizationManagerFactory) { |
| 112 | + this.authorizationManager.setAuthoritiesAuthorizationManager( |
| 113 | + new DelegatingAuthoritiesAuthorizationManager(authorizationManagerFactory)); |
| 114 | + } |
| 115 | + |
| 116 | + private static final class DelegatingAuthoritiesAuthorizationManager |
| 117 | + implements AuthorizationManager<Collection<String>> { |
| 118 | + |
| 119 | + private static final String[] STRING_ARRAY = new String[0]; |
| 120 | + |
| 121 | + private final AuthorizationManagerFactory<Collection<String>> authorizationManagerFactory; |
| 122 | + |
| 123 | + private final Map<Collection<String>, AuthorizationManager<Collection<String>>> cachedAuthorizationManagers = new ConcurrentHashMap<>(); |
| 124 | + |
| 125 | + private DelegatingAuthoritiesAuthorizationManager( |
| 126 | + AuthorizationManagerFactory<Collection<String>> authorizationManagerFactory) { |
| 127 | + this.authorizationManagerFactory = authorizationManagerFactory; |
| 128 | + } |
| 129 | + |
| 130 | + @Override |
| 131 | + public @Nullable AuthorizationResult authorize(Supplier<Authentication> authentication, |
| 132 | + Collection<String> authorities) { |
| 133 | + AuthorizationManager<Collection<String>> delegate = getAuthorizationManager(authorities); |
| 134 | + return delegate.authorize(authentication, authorities); |
| 135 | + } |
| 136 | + |
| 137 | + private AuthorizationManager<Collection<String>> getAuthorizationManager(Collection<String> authorities) { |
| 138 | + return this.cachedAuthorizationManagers.computeIfAbsent(authorities, |
| 139 | + (k) -> this.authorizationManagerFactory.hasAnyAuthority(authorities.toArray(STRING_ARRAY))); |
| 140 | + } |
| 141 | + |
| 142 | + } |
| 143 | + |
104 | 144 | }
|
0 commit comments