Skip to content
Merged
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 @@ -134,6 +134,19 @@ public static <T> AllAuthoritiesAuthorizationManager<T> hasAllAuthorities(String
return new AllAuthoritiesAuthorizationManager<>(authorities);
}

/**
* Creates an instance of {@link AllAuthoritiesAuthorizationManager} with the provided
* authorities.
* @param authorities the authorities to check for
* @param <T> the type of object being authorized
* @return the new instance
*/
public static <T> AllAuthoritiesAuthorizationManager<T> hasAllAuthorities(List<String> authorities) {
Assert.notEmpty(authorities, "authorities cannot be empty");
Assert.noNullElements(authorities, "authorities cannot contain null values");
return new AllAuthoritiesAuthorizationManager<>(authorities.toArray(new String[0]));
}

private static String[] toNamedRolesArray(String rolePrefix, String[] roles) {
String[] result = new String[roles.length];
for (int i = 0; i < roles.length; i++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,25 @@

package org.springframework.security.authorization;

import java.util.ArrayList;
import java.util.List;

import org.jspecify.annotations.Nullable;

import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
import org.springframework.security.authentication.AuthenticationTrustResolver;
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

/**
* A factory for creating different kinds of {@link AuthorizationManager} instances.
*
* @param <T> the type of object that the authorization check is being done on
* @author Steve Riesenberg
* @author Andrey Litvitski
* @author Rob Winch
* @since 7.0
*/
public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object>
Expand All @@ -40,6 +46,8 @@ public final class DefaultAuthorizationManagerFactory<T extends @Nullable Object

private String rolePrefix = "ROLE_";

private @Nullable AuthorizationManager<T> additionalAuthorization;

/**
* Sets the {@link AuthenticationTrustResolver} used to check the user's
* authentication.
Expand Down Expand Up @@ -69,71 +77,173 @@ public void setRolePrefix(String rolePrefix) {
this.rolePrefix = rolePrefix;
}

/**
* Sets additional authorization to be applied to the returned
* {@link AuthorizationManager} for the following methods:
*
* <ul>
* <li>{@link #hasRole(String)}</li>
* <li>{@link #hasAnyRole(String...)}</li>
* <li>{@link #hasAllRoles(String...)}</li>
* <li>{@link #hasAuthority(String)}</li>
* <li>{@link #hasAnyAuthority(String...)}</li>
* <li>{@link #hasAllAuthorities(String...)}</li>
* <li>{@link #authenticated()}</li>
* <li>{@link #fullyAuthenticated()}</li>
* <li>{@link #rememberMe()}</li>
* </ul>
*
* <p>
* This does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
* </p>
* @param additionalAuthorization the {@link AuthorizationManager} to be applied.
* Default is null (no additional authorization).
*/
public void setAdditionalAuthorization(@Nullable AuthorizationManager<T> additionalAuthorization) {
this.additionalAuthorization = additionalAuthorization;
}

@Override
public AuthorizationManager<T> hasRole(String role) {
return hasAnyRole(role);
}

@Override
public AuthorizationManager<T> hasAnyRole(String... roles) {
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, roles));
return createManager(AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, roles));
}

@Override
public AuthorizationManager<T> hasAllRoles(String... roles) {
return withRoleHierarchy(AllAuthoritiesAuthorizationManager.hasAllPrefixedAuthorities(this.rolePrefix, roles));
return createManager(AllAuthoritiesAuthorizationManager.hasAllPrefixedAuthorities(this.rolePrefix, roles));
}

@Override
public AuthorizationManager<T> hasAuthority(String authority) {
return withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority));
return createManager(AuthorityAuthorizationManager.hasAuthority(authority));
}

@Override
public AuthorizationManager<T> hasAnyAuthority(String... authorities) {
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities));
return createManager(AuthorityAuthorizationManager.hasAnyAuthority(authorities));
}

@Override
public AuthorizationManager<T> hasAllAuthorities(String... authorities) {
return withRoleHierarchy(AllAuthoritiesAuthorizationManager.hasAllAuthorities(authorities));
return createManager(AllAuthoritiesAuthorizationManager.hasAllAuthorities(authorities));
}

@Override
public AuthorizationManager<T> authenticated() {
return withTrustResolver(AuthenticatedAuthorizationManager.authenticated());
return createManager(AuthenticatedAuthorizationManager.authenticated());
}

@Override
public AuthorizationManager<T> fullyAuthenticated() {
return withTrustResolver(AuthenticatedAuthorizationManager.fullyAuthenticated());
return createManager(AuthenticatedAuthorizationManager.fullyAuthenticated());
}

@Override
public AuthorizationManager<T> rememberMe() {
return withTrustResolver(AuthenticatedAuthorizationManager.rememberMe());
return createManager(AuthenticatedAuthorizationManager.rememberMe());
}

@Override
public AuthorizationManager<T> anonymous() {
return withTrustResolver(AuthenticatedAuthorizationManager.anonymous());
return createManager(AuthenticatedAuthorizationManager.anonymous());
}

private AuthorityAuthorizationManager<T> withRoleHierarchy(AuthorityAuthorizationManager<T> authorizationManager) {
/**
* Creates a {@link Builder} that helps build an {@link AuthorizationManager} to set
* on {@link #setAdditionalAuthorization(AuthorizationManager)} for common scenarios.
* <p>
* Does not affect {@code anonymous}, {@code permitAll}, or {@code denyAll}.
* @param <T> the secured object type
* @return a factory configured with the required authorities
*/
public static <T> Builder<T> builder() {
return new Builder<>();
}

private AuthorizationManager<T> createManager(AuthorityAuthorizationManager<T> authorizationManager) {
authorizationManager.setRoleHierarchy(this.roleHierarchy);
return authorizationManager;
return withAdditionalAuthorization(authorizationManager);
}

private AllAuthoritiesAuthorizationManager<T> withRoleHierarchy(
AllAuthoritiesAuthorizationManager<T> authorizationManager) {
private AuthorizationManager<T> createManager(AllAuthoritiesAuthorizationManager<T> authorizationManager) {
authorizationManager.setRoleHierarchy(this.roleHierarchy);
return authorizationManager;
return withAdditionalAuthorization(authorizationManager);
}

private AuthenticatedAuthorizationManager<T> withTrustResolver(
AuthenticatedAuthorizationManager<T> authorizationManager) {
private AuthorizationManager<T> createManager(AuthenticatedAuthorizationManager<T> authorizationManager) {
authorizationManager.setTrustResolver(this.trustResolver);
return authorizationManager;
return withAdditionalAuthorization(authorizationManager);
}

private AuthorizationManager<T> withAdditionalAuthorization(AuthorizationManager<T> manager) {
if (this.additionalAuthorization == null) {
return manager;
}
return AuthorizationManagers.allOf(new AuthorizationDecision(false), this.additionalAuthorization, manager);
}

/**
* A builder that allows creating {@link DefaultAuthorizationManagerFactory} with
* additional authorization for common scenarios.
*
* @param <T> the type for the {@link DefaultAuthorizationManagerFactory}
* @author Rob Winch
*/
public static final class Builder<T> {

private final List<String> additionalAuthorities = new ArrayList<>();

private RoleHierarchy roleHierarchy = new NullRoleHierarchy();

/**
* Add additional authorities that will be required.
* @param additionalAuthorities the additional authorities.
* @return the {@link Builder} to further customize.
*/
public Builder<T> requireAdditionalAuthorities(String... additionalAuthorities) {
Assert.notEmpty(additionalAuthorities, "additionalAuthorities cannot be empty");
for (String additionalAuthority : additionalAuthorities) {
this.additionalAuthorities.add(additionalAuthority);
}
return this;
}

/**
* The {@link RoleHierarchy} to use.
* @param roleHierarchy the non-null {@link RoleHierarchy} to use. Default is
* {@link NullRoleHierarchy}.
* @return the Builder to further customize.
*/
public Builder<T> roleHierarchy(RoleHierarchy roleHierarchy) {
Assert.notNull(roleHierarchy, "roleHierarchy cannot be null");
this.roleHierarchy = roleHierarchy;
return this;
}

/**
* Builds a {@link DefaultAuthorizationManagerFactory} that has the
* {@link #setAdditionalAuthorization(AuthorizationManager)} set.
* @return the {@link DefaultAuthorizationManagerFactory}.
*/
public DefaultAuthorizationManagerFactory<T> build() {
Assert.state(!CollectionUtils.isEmpty(this.additionalAuthorities), "additionalAuthorities cannot be empty");
DefaultAuthorizationManagerFactory<T> result = new DefaultAuthorizationManagerFactory<>();
AllAuthoritiesAuthorizationManager<T> additionalChecks = AllAuthoritiesAuthorizationManager
.hasAllAuthorities(this.additionalAuthorities);
result.setRoleHierarchy(this.roleHierarchy);
additionalChecks.setRoleHierarchy(this.roleHierarchy);
result.setAdditionalAuthorization(additionalChecks);
return result;
}

private Builder() {
}

}

}
Loading