Skip to content

Add AuthorizationManagerFactory #17673

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.aot.hint.PrePostAuthorizeHintsRegistrar;
import org.springframework.security.aot.hint.SecurityHintsRegistrar;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authorization.AuthorizationEventPublisher;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationManagerFactory;
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
import org.springframework.security.authorization.method.MethodInvocationResult;
Expand Down Expand Up @@ -121,6 +123,16 @@ void setRoleHierarchy(RoleHierarchy roleHierarchy) {
this.expressionHandler.setRoleHierarchy(roleHierarchy);
}

@Autowired(required = false)
void setTrustResolver(AuthenticationTrustResolver trustResolver) {
this.expressionHandler.setTrustResolver(trustResolver);
}

@Autowired(required = false)
void setAuthorizationManagerFactory(AuthorizationManagerFactory<MethodInvocation> authorizationManagerFactory) {
this.expressionHandler.setAuthorizationManagerFactory(authorizationManagerFactory);
}

@Autowired(required = false)
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import java.util.List;
import java.util.function.Function;
import java.util.function.Supplier;

import jakarta.servlet.http.HttpServletRequest;

Expand All @@ -27,13 +26,12 @@
import org.springframework.core.ResolvableType;
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
import org.springframework.security.authorization.AuthorityAuthorizationManager;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.AuthorizationEventPublisher;
import org.springframework.security.authorization.AuthorizationManager;
import org.springframework.security.authorization.AuthorizationManagerFactory;
import org.springframework.security.authorization.AuthorizationManagers;
import org.springframework.security.authorization.SingleResultAuthorizationManager;
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
import org.springframework.security.authorization.SpringAuthorizationEventPublisher;
import org.springframework.security.config.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.AbstractRequestMatcherRegistry;
Expand All @@ -46,7 +44,6 @@
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcherEntry;
import org.springframework.util.Assert;
import org.springframework.util.function.SingletonSupplier;

/**
* Adds a URL based authorization using {@link AuthorizationManager}.
Expand All @@ -62,9 +59,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder

private final AuthorizationEventPublisher publisher;

private final Supplier<RoleHierarchy> roleHierarchy;

private String rolePrefix = "ROLE_";
private final AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;

private ObjectPostProcessor<AuthorizationManager<HttpServletRequest>> postProcessor = ObjectPostProcessor
.identity();
Expand All @@ -81,20 +76,36 @@ public AuthorizeHttpRequestsConfigurer(ApplicationContext context) {
else {
this.publisher = new SpringAuthorizationEventPublisher(context);
}
this.roleHierarchy = SingletonSupplier.of(() -> (context.getBeanNamesForType(RoleHierarchy.class).length > 0)
? context.getBean(RoleHierarchy.class) : new NullRoleHierarchy());
String[] grantedAuthorityDefaultsBeanNames = context.getBeanNamesForType(GrantedAuthorityDefaults.class);
if (grantedAuthorityDefaultsBeanNames.length > 0) {
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBean(GrantedAuthorityDefaults.class);
this.rolePrefix = grantedAuthorityDefaults.getRolePrefix();
}
this.authorizationManagerFactory = getAuthorizationManagerFactory(context);
ResolvableType type = ResolvableType.forClassWithGenerics(ObjectPostProcessor.class,
ResolvableType.forClassWithGenerics(AuthorizationManager.class, HttpServletRequest.class));
ObjectProvider<ObjectPostProcessor<AuthorizationManager<HttpServletRequest>>> provider = context
.getBeanProvider(type);
provider.ifUnique((postProcessor) -> this.postProcessor = postProcessor);
}

private AuthorizationManagerFactory<RequestAuthorizationContext> getAuthorizationManagerFactory(
ApplicationContext context) {
ResolvableType authorizationManagerFactoryType = ResolvableType
.forClassWithGenerics(AuthorizationManagerFactory.class, RequestAuthorizationContext.class);
ObjectProvider<AuthorizationManagerFactory<RequestAuthorizationContext>> authorizationManagerFactoryProvider = context
.getBeanProvider(authorizationManagerFactoryType);

return authorizationManagerFactoryProvider.getIfAvailable(() -> {
RoleHierarchy roleHierarchy = context.getBeanProvider(RoleHierarchy.class)
.getIfAvailable(NullRoleHierarchy::new);
GrantedAuthorityDefaults grantedAuthorityDefaults = context.getBeanProvider(GrantedAuthorityDefaults.class)
.getIfAvailable();
String rolePrefix = (grantedAuthorityDefaults != null) ? grantedAuthorityDefaults.getRolePrefix() : "ROLE_";

DefaultAuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory = new DefaultAuthorizationManagerFactory<>();
authorizationManagerFactory.setRoleHierarchy(roleHierarchy);
authorizationManagerFactory.setRolePrefix(rolePrefix);

return authorizationManagerFactory;
});
}

/**
* The {@link AuthorizationManagerRequestMatcherRegistry} is what users will interact
* with after applying the {@link AuthorizeHttpRequestsConfigurer}.
Expand Down Expand Up @@ -173,7 +184,7 @@ private AuthorizationManager<HttpServletRequest> createAuthorizationManager() {
@Override
protected AuthorizedUrl chainRequestMatchers(List<RequestMatcher> requestMatchers) {
this.unmappedMatchers = requestMatchers;
return new AuthorizedUrl(requestMatchers);
return new AuthorizedUrl(requestMatchers, AuthorizeHttpRequestsConfigurer.this.authorizationManagerFactory);
}

/**
Expand Down Expand Up @@ -201,20 +212,31 @@ public class AuthorizedUrl {

private final List<? extends RequestMatcher> matchers;

private AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory;

private boolean not;

/**
* Creates an instance.
* @param matchers the {@link RequestMatcher} instances to map
* @param authorizationManagerFactory the {@link AuthorizationManagerFactory} for
* creating instances of {@link AuthorizationManager}
*/
AuthorizedUrl(List<? extends RequestMatcher> matchers) {
AuthorizedUrl(List<? extends RequestMatcher> matchers,
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory) {
this.matchers = matchers;
this.authorizationManagerFactory = authorizationManagerFactory;
}

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

void setAuthorizationManagerFactory(
AuthorizationManagerFactory<RequestAuthorizationContext> authorizationManagerFactory) {
this.authorizationManagerFactory = authorizationManagerFactory;
}

/**
* Negates the following authorization rule.
* @return the {@link AuthorizedUrl} for further customization
Expand All @@ -231,7 +253,7 @@ public AuthorizedUrl not() {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry permitAll() {
return access(SingleResultAuthorizationManager.permitAll());
return access(this.authorizationManagerFactory.permitAll());
}

/**
Expand All @@ -240,7 +262,7 @@ public AuthorizationManagerRequestMatcherRegistry permitAll() {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry denyAll() {
return access(SingleResultAuthorizationManager.denyAll());
return access(this.authorizationManagerFactory.denyAll());
}

/**
Expand All @@ -251,8 +273,7 @@ public AuthorizationManagerRequestMatcherRegistry denyAll() {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
return access(withRoleHierarchy(AuthorityAuthorizationManager
.hasAnyRole(AuthorizeHttpRequestsConfigurer.this.rolePrefix, new String[] { role })));
return access(this.authorizationManagerFactory.hasRole(role));
}

/**
Expand All @@ -264,8 +285,7 @@ public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
return access(withRoleHierarchy(
AuthorityAuthorizationManager.hasAnyRole(AuthorizeHttpRequestsConfigurer.this.rolePrefix, roles)));
return access(this.authorizationManagerFactory.hasAnyRole(roles));
}

/**
Expand All @@ -275,7 +295,7 @@ public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority) {
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority)));
return access(this.authorizationManagerFactory.hasAuthority(authority));
}

/**
Expand All @@ -286,13 +306,7 @@ public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority)
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority(String... authorities) {
return access(withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities)));
}

private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHierarchy(
AuthorityAuthorizationManager<RequestAuthorizationContext> manager) {
manager.setRoleHierarchy(AuthorizeHttpRequestsConfigurer.this.roleHierarchy.get());
return manager;
return access(this.authorizationManagerFactory.hasAnyAuthority(authorities));
}

/**
Expand All @@ -301,7 +315,7 @@ private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHiera
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry authenticated() {
return access(AuthenticatedAuthorizationManager.authenticated());
return access(this.authorizationManagerFactory.authenticated());
}

/**
Expand All @@ -313,7 +327,7 @@ public AuthorizationManagerRequestMatcherRegistry authenticated() {
* @see RememberMeConfigurer
*/
public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
return access(AuthenticatedAuthorizationManager.fullyAuthenticated());
return access(this.authorizationManagerFactory.fullyAuthenticated());
}

/**
Expand All @@ -324,7 +338,7 @@ public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
* @see RememberMeConfigurer
*/
public AuthorizationManagerRequestMatcherRegistry rememberMe() {
return access(AuthenticatedAuthorizationManager.rememberMe());
return access(this.authorizationManagerFactory.rememberMe());
}

/**
Expand All @@ -334,7 +348,7 @@ public AuthorizationManagerRequestMatcherRegistry rememberMe() {
* @since 5.8
*/
public AuthorizationManagerRequestMatcherRegistry anonymous() {
return access(AuthenticatedAuthorizationManager.anonymous());
return access(this.authorizationManagerFactory.anonymous());
}

/**
Expand Down
Loading
Loading