Skip to content

Commit eeb4574

Browse files
sjohnrrwinch
authored andcommitted
Add AuthorizationManagerFactory
Signed-off-by: Steve Riesenberg <[email protected]>
1 parent a4f813a commit eeb4574

File tree

37 files changed

+2718
-177
lines changed

37 files changed

+2718
-177
lines changed

config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.springframework.security.aot.hint.SecurityHintsRegistrar;
4040
import org.springframework.security.authorization.AuthorizationEventPublisher;
4141
import org.springframework.security.authorization.AuthorizationManager;
42+
import org.springframework.security.authorization.AuthorizationManagerFactory;
4243
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
4344
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
4445
import org.springframework.security.authorization.method.MethodInvocationResult;
@@ -121,6 +122,11 @@ void setRoleHierarchy(RoleHierarchy roleHierarchy) {
121122
this.expressionHandler.setRoleHierarchy(roleHierarchy);
122123
}
123124

125+
@Autowired(required = false)
126+
void setAuthorizationManagerFactory(AuthorizationManagerFactory<MethodInvocation> authorizationManagerFactory) {
127+
this.expressionHandler.setAuthorizationManagerFactory(authorizationManagerFactory);
128+
}
129+
124130
@Autowired(required = false)
125131
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
126132
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);

config/src/main/java/org/springframework/security/config/annotation/web/configurers/AuthorizeHttpRequestsConfigurer.java

Lines changed: 57 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.util.List;
2020
import java.util.function.Function;
21-
import java.util.function.Supplier;
2221

2322
import jakarta.servlet.http.HttpServletRequest;
2423

@@ -27,13 +26,12 @@
2726
import org.springframework.core.ResolvableType;
2827
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
2928
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
30-
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
31-
import org.springframework.security.authorization.AuthorityAuthorizationManager;
3229
import org.springframework.security.authorization.AuthorizationDecision;
3330
import org.springframework.security.authorization.AuthorizationEventPublisher;
3431
import org.springframework.security.authorization.AuthorizationManager;
32+
import org.springframework.security.authorization.AuthorizationManagerFactory;
3533
import org.springframework.security.authorization.AuthorizationManagers;
36-
import org.springframework.security.authorization.SingleResultAuthorizationManager;
34+
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
3735
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
3836
import org.springframework.security.config.ObjectPostProcessor;
3937
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
@@ -46,13 +44,13 @@
4644
import org.springframework.security.web.util.matcher.RequestMatcher;
4745
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
4846
import org.springframework.util.Assert;
49-
import org.springframework.util.function.SingletonSupplier;
5047

5148
/**
5249
* Adds a URL based authorization using {@link AuthorizationManager}.
5350
*
5451
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured.
5552
* @author Evgeniy Cheban
53+
* @author Steve Riesenberg
5654
* @since 5.5
5755
*/
5856
public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder<H>>
@@ -62,9 +60,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
6260

6361
private final AuthorizationEventPublisher publisher;
6462

65-
private final Supplier<RoleHierarchy> roleHierarchy;
66-
67-
private String rolePrefix = "ROLE_";
63+
private final AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;
6864

6965
private ObjectPostProcessor<AuthorizationManager<HttpServletRequest>> postProcessor = ObjectPostProcessor
7066
.identity();
@@ -81,20 +77,43 @@ public AuthorizeHttpRequestsConfigurer(ApplicationContext context) {
8177
else {
8278
this.publisher = new SpringAuthorizationEventPublisher(context);
8379
}
84-
this.roleHierarchy = SingletonSupplier.of(() -> (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
85-
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy());
86-
String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
87-
if (grantedAuthorityDefaultsBeanNames.length > 0) {
88-
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(GrantedAuthorityDefaults.class);
89-
this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
90-
}
80+
this.authorizationManagerFactory = getAuthorizationManagerFactory(context);
9181
ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class,
9282
ResolvableType.forClassWithGenerics(AuthorizationManager.class, HttpServletRequest.class));
9383
ObjectProvider<ObjectPostProcessor<AuthorizationManager<HttpServletRequest>>> provider = context
9484
.getBeanProvider(type);
9585
provider.ifUnique((postProcessor) -> this.postProcessor = postProcessor);
9686
}
9787

88+
private AuthorizationManagerFactory<RequestAuthorizationContext> getAuthorizationManagerFactory(
89+
ApplicationContext context) {
90+
ResolvableType authorizationManagerFactoryType = ResolvableType
91+
.forClassWithGenerics(AuthorizationManagerFactory.class, RequestAuthorizationContext.class);
92+
93+
// Handle fallback to generic type
94+
if (context.getBeanNamesForType(authorizationManagerFactoryType).length == 0) {
95+
authorizationManagerFactoryType = ResolvableType.forClassWithGenerics(AuthorizationManagerFactory.class,
96+
Object.class);
97+
}
98+
99+
ObjectProvider<AuthorizationManagerFactory<RequestAuthorizationContext>> authorizationManagerFactoryProvider = context
100+
.getBeanProvider(authorizationManagerFactoryType);
101+
102+
return authorizationManagerFactoryProvider.getIfAvailable(() -> {
103+
RoleHierarchy roleHierarchy = context.getBeanProvider(RoleHierarchy.class)
104+
.getIfAvailable(NullRoleHierarchy::new);
105+
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBeanProvider(GrantedAuthorityDefaults.class)
106+
.getIfAvailable();
107+
String rolePrefix = (grantedAuthorityDefaults != null) ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";
108+
109+
DefaultAuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = new DefaultAuthorizationManagerFactory<>();
110+
authorizationManagerFactory.setRoleHierarchy(roleHierarchy);
111+
authorizationManagerFactory.setRolePrefix(rolePrefix);
112+
113+
return authorizationManagerFactory;
114+
});
115+
}
116+
98117
/**
99118
* The {@link AuthorizationManagerRequestMatcherRegistry} is what users will interact
100119
* with after applying the {@link AuthorizeHttpRequestsConfigurer}.
@@ -173,7 +192,7 @@ private AuthorizationManager<HttpServletRequest> createAuthorizationManager() {
173192
@Override
174193
protected AuthorizedUrl chainRequestMatchers(List<RequestMatcher> requestMatchers) {
175194
this.unmappedMatchers = requestMatchers;
176-
return new AuthorizedUrl(requestMatchers);
195+
return new AuthorizedUrl(requestMatchers, AuthorizeHttpRequestsConfigurer.this.authorizationManagerFactory);
177196
}
178197

179198
/**
@@ -201,20 +220,31 @@ public class AuthorizedUrl {
201220

202221
private final List<? extends RequestMatcher> matchers;
203222

223+
private AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;
224+
204225
private boolean not;
205226

206227
/**
207228
* Creates an instance.
208229
* @param matchers the {@link RequestMatcher} instances to map
230+
* @param authorizationManagerFactory the {@link AuthorizationManagerFactory} for
231+
* creating instances of {@link AuthorizationManager}
209232
*/
210-
AuthorizedUrl(List<? extends RequestMatcher> matchers) {
233+
AuthorizedUrl(List<? extends RequestMatcher> matchers,
234+
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory) {
211235
this.matchers = matchers;
236+
this.authorizationManagerFactory = authorizationManagerFactory;
212237
}
213238

214239
protected List<? extends RequestMatcher> getMatchers() {
215240
return this.matchers;
216241
}
217242

243+
void setAuthorizationManagerFactory(
244+
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory) {
245+
this.authorizationManagerFactory = authorizationManagerFactory;
246+
}
247+
218248
/**
219249
* Negates the following authorization rule.
220250
* @return the {@link AuthorizedUrl} for further customization
@@ -231,7 +261,7 @@ public AuthorizedUrl not() {
231261
* customizations
232262
*/
233263
public AuthorizationManagerRequestMatcherRegistry permitAll() {
234-
return access(SingleResultAuthorizationManager.permitAll());
264+
return access(this.authorizationManagerFactory.permitAll());
235265
}
236266

237267
/**
@@ -240,7 +270,7 @@ public AuthorizationManagerRequestMatcherRegistry permitAll() {
240270
* customizations
241271
*/
242272
public AuthorizationManagerRequestMatcherRegistry denyAll() {
243-
return access(SingleResultAuthorizationManager.denyAll());
273+
return access(this.authorizationManagerFactory.denyAll());
244274
}
245275

246276
/**
@@ -251,8 +281,7 @@ public AuthorizationManagerRequestMatcherRegistry denyAll() {
251281
* customizations
252282
*/
253283
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
254-
return access(withRoleHierarchy(AuthorityAuthorizationManager
255-
.hasAnyRole(AuthorizeHttpRequestsConfigurer.this.rolePrefix, new String[] { role })));
284+
return access(this.authorizationManagerFactory.hasRole(role));
256285
}
257286

258287
/**
@@ -264,8 +293,7 @@ public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
264293
* customizations
265294
*/
266295
public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
267-
return access(withRoleHierarchy(
268-
AuthorityAuthorizationManager.hasAnyRole(AuthorizeHttpRequestsConfigurer.this.rolePrefix, roles)));
296+
return access(this.authorizationManagerFactory.hasAnyRole(roles));
269297
}
270298

271299
/**
@@ -275,7 +303,7 @@ public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
275303
* customizations
276304
*/
277305
public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority) {
278-
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority)));
306+
return access(this.authorizationManagerFactory.hasAuthority(authority));
279307
}
280308

281309
/**
@@ -286,13 +314,7 @@ public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority)
286314
* customizations
287315
*/
288316
public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority(String... authorities) {
289-
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)));
290-
}
291-
292-
private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHierarchy(
293-
AuthorityAuthorizationManager<RequestAuthorizationContext> manager) {
294-
manager.setRoleHierarchy(AuthorizeHttpRequestsConfigurer.this.roleHierarchy.get());
295-
return manager;
317+
return access(this.authorizationManagerFactory.hasAnyAuthority(authorities));
296318
}
297319

298320
/**
@@ -301,7 +323,7 @@ private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHiera
301323
* customizations
302324
*/
303325
public AuthorizationManagerRequestMatcherRegistry authenticated() {
304-
return access(AuthenticatedAuthorizationManager.authenticated());
326+
return access(this.authorizationManagerFactory.authenticated());
305327
}
306328

307329
/**
@@ -313,7 +335,7 @@ public AuthorizationManagerRequestMatcherRegistry authenticated() {
313335
* @see RememberMeConfigurer
314336
*/
315337
public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
316-
return access(AuthenticatedAuthorizationManager.fullyAuthenticated());
338+
return access(this.authorizationManagerFactory.fullyAuthenticated());
317339
}
318340

319341
/**
@@ -324,7 +346,7 @@ public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
324346
* @see RememberMeConfigurer
325347
*/
326348
public AuthorizationManagerRequestMatcherRegistry rememberMe() {
327-
return access(AuthenticatedAuthorizationManager.rememberMe());
349+
return access(this.authorizationManagerFactory.rememberMe());
328350
}
329351

330352
/**
@@ -334,7 +356,7 @@ public AuthorizationManagerRequestMatcherRegistry rememberMe() {
334356
* @since 5.8
335357
*/
336358
public AuthorizationManagerRequestMatcherRegistry anonymous() {
337-
return access(AuthenticatedAuthorizationManager.anonymous());
359+
return access(this.authorizationManagerFactory.anonymous());
338360
}
339361

340362
/**

0 commit comments

Comments
 (0)