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,13 +44,13 @@
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}.
*
* @param <H> the type of {@link HttpSecurityBuilder} that is being configured.
* @author Evgeniy Cheban
* @author Steve Riesenberg
* @since 5.5
*/
public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder<H>>
Expand All
@@ -62,9 +60,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 +77,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 +185,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 +213,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 +254,7 @@ public AuthorizedUrl not() {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry permitAll() {
return access(SingleResultAuthorizationManager .permitAll());
return access(this.authorizationManagerFactory .permitAll());
}
/**
Expand All
@@ -240,7 +263,7 @@ public AuthorizationManagerRequestMatcherRegistry permitAll() {
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry denyAll() {
return access(SingleResultAuthorizationManager .denyAll());
return access(this.authorizationManagerFactory .denyAll());
}
/**
Expand All
@@ -251,8 +274,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 +286,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 +296,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 +307,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 +316,7 @@ private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHiera
* customizations
*/
public AuthorizationManagerRequestMatcherRegistry authenticated() {
return access(AuthenticatedAuthorizationManager .authenticated());
return access(this.authorizationManagerFactory .authenticated());
}
/**
Expand All
@@ -313,7 +328,7 @@ public AuthorizationManagerRequestMatcherRegistry authenticated() {
* @see RememberMeConfigurer
*/
public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
return access(AuthenticatedAuthorizationManager .fullyAuthenticated());
return access(this.authorizationManagerFactory .fullyAuthenticated());
}
/**
Expand All
@@ -324,7 +339,7 @@ public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
* @see RememberMeConfigurer
*/
public AuthorizationManagerRequestMatcherRegistry rememberMe() {
return access(AuthenticatedAuthorizationManager .rememberMe());
return access(this.authorizationManagerFactory .rememberMe());
}
/**
Expand All
@@ -334,7 +349,7 @@ public AuthorizationManagerRequestMatcherRegistry rememberMe() {
* @since 5.8
*/
public AuthorizationManagerRequestMatcherRegistry anonymous() {
return access(AuthenticatedAuthorizationManager .anonymous());
return access(this.authorizationManagerFactory .anonymous());
}
/**
Expand Down