Add AuthorizationManagerFactory
Signed-off-by: Steve Riesenberg <5248162+sjohnr@users.noreply.github.com>
This commit is contained in:
committed by
Rob Winch
parent
a4f813ab29
commit
eeb4574bb3
+53
-11
@@ -26,6 +26,8 @@ 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.security.authorization.AuthorizationManagerFactory;
|
||||
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
@@ -92,18 +94,18 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class SecurityEvaluationContextExtension implements EvaluationContextExtension {
|
||||
|
||||
private static final String DEFAULT_ROLE_PREFIX = "ROLE_";
|
||||
|
||||
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
|
||||
.getContextHolderStrategy();
|
||||
|
||||
private @Nullable Authentication authentication;
|
||||
|
||||
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
|
||||
private RoleHierarchy roleHierarchy = new NullRoleHierarchy();
|
||||
private AuthorizationManagerFactory<Object> authorizationManagerFactory = new DefaultAuthorizationManagerFactory<>();
|
||||
|
||||
private PermissionEvaluator permissionEvaluator = new DenyAllPermissionEvaluator();
|
||||
|
||||
private String defaultRolePrefix = "ROLE_";
|
||||
private String defaultRolePrefix = DEFAULT_ROLE_PREFIX;
|
||||
|
||||
/**
|
||||
* Creates a new instance that uses the current {@link Authentication} found on the
|
||||
@@ -126,14 +128,16 @@ public class SecurityEvaluationContextExtension implements EvaluationContextExte
|
||||
}
|
||||
|
||||
@Override
|
||||
public SecurityExpressionRoot getRootObject() {
|
||||
public SecurityExpressionRoot<Object> getRootObject() {
|
||||
Authentication authentication = getAuthentication();
|
||||
SecurityExpressionRoot root = new SecurityExpressionRoot(authentication) {
|
||||
SecurityExpressionRoot<Object> root = new SecurityExpressionRoot<>(() -> authentication, new Object()) {
|
||||
};
|
||||
root.setTrustResolver(this.trustResolver);
|
||||
root.setRoleHierarchy(this.roleHierarchy);
|
||||
root.setAuthorizationManagerFactory(this.authorizationManagerFactory);
|
||||
root.setPermissionEvaluator(this.permissionEvaluator);
|
||||
root.setDefaultRolePrefix(this.defaultRolePrefix);
|
||||
if (!DEFAULT_ROLE_PREFIX.equals(this.defaultRolePrefix)) {
|
||||
// Ensure SecurityExpressionRoot can strip the custom role prefix
|
||||
root.setDefaultRolePrefix(this.defaultRolePrefix);
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -156,15 +160,46 @@ public class SecurityEvaluationContextExtension implements EvaluationContextExte
|
||||
return context.getAuthentication();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthorizationManagerFactory} to be used. The default is
|
||||
* {@link DefaultAuthorizationManagerFactory}.
|
||||
* @param authorizationManagerFactory the {@link AuthorizationManagerFactory} to use.
|
||||
* Cannot be null.
|
||||
* @since 7.0
|
||||
*/
|
||||
public void setAuthorizationManagerFactory(AuthorizationManagerFactory<Object> authorizationManagerFactory) {
|
||||
Assert.notNull(authorizationManagerFactory, "authorizationManagerFactory cannot be null");
|
||||
this.authorizationManagerFactory = authorizationManagerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows accessing the {@link DefaultAuthorizationManagerFactory} for getting and
|
||||
* setting defaults. This method will be removed in Spring Security 8.
|
||||
* @return the {@link DefaultAuthorizationManagerFactory}
|
||||
* @throws IllegalStateException if a different {@link AuthorizationManagerFactory}
|
||||
* was already set
|
||||
*/
|
||||
private DefaultAuthorizationManagerFactory<Object> getDefaultAuthorizationManagerFactory() {
|
||||
if (!(this.authorizationManagerFactory instanceof DefaultAuthorizationManagerFactory<Object> defaultAuthorizationManagerFactory)) {
|
||||
throw new IllegalStateException(
|
||||
"authorizationManagerFactory must be an instance of DefaultAuthorizationManagerFactory");
|
||||
}
|
||||
|
||||
return defaultAuthorizationManagerFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link AuthenticationTrustResolver} to be used. Default is
|
||||
* {@link AuthenticationTrustResolverImpl}. Cannot be null.
|
||||
* @param trustResolver the {@link AuthenticationTrustResolver} to use
|
||||
* @since 5.8
|
||||
* @deprecated Use
|
||||
* {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
|
||||
Assert.notNull(trustResolver, "trustResolver cannot be null");
|
||||
this.trustResolver = trustResolver;
|
||||
getDefaultAuthorizationManagerFactory().setTrustResolver(trustResolver);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -172,10 +207,13 @@ public class SecurityEvaluationContextExtension implements EvaluationContextExte
|
||||
* Cannot be null.
|
||||
* @param roleHierarchy the {@link RoleHierarchy} to use
|
||||
* @since 5.8
|
||||
* @deprecated Use
|
||||
* {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
|
||||
Assert.notNull(roleHierarchy, "roleHierarchy cannot be null");
|
||||
this.roleHierarchy = roleHierarchy;
|
||||
getDefaultAuthorizationManagerFactory().setRoleHierarchy(roleHierarchy);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,8 +237,12 @@ public class SecurityEvaluationContextExtension implements EvaluationContextExte
|
||||
* @param defaultRolePrefix the default prefix to add to roles. The default is
|
||||
* "ROLE_".
|
||||
* @since 5.8
|
||||
* @deprecated Use
|
||||
* {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
|
||||
*/
|
||||
@Deprecated(since = "7.0")
|
||||
public void setDefaultRolePrefix(String defaultRolePrefix) {
|
||||
getDefaultAuthorizationManagerFactory().setRolePrefix(defaultRolePrefix);
|
||||
this.defaultRolePrefix = defaultRolePrefix;
|
||||
}
|
||||
|
||||
|
||||
+16
-15
@@ -23,10 +23,9 @@ import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.access.PermissionEvaluator;
|
||||
import org.springframework.security.access.expression.DenyAllPermissionEvaluator;
|
||||
import org.springframework.security.access.expression.SecurityExpressionRoot;
|
||||
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
|
||||
import org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolver;
|
||||
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
|
||||
import org.springframework.security.authentication.TestingAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.context.SecurityContextHolderStrategy;
|
||||
@@ -102,9 +101,11 @@ public class SecurityEvaluationContextExtensionTests {
|
||||
public void setTrustResolverWhenNotNullThenVerifyRootObject() {
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT");
|
||||
this.securityExtension = new SecurityEvaluationContextExtension(explicit);
|
||||
AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
|
||||
AuthenticationTrustResolver trustResolver = mock(AuthenticationTrustResolver.class);
|
||||
given(trustResolver.isAuthenticated(explicit)).willReturn(true);
|
||||
this.securityExtension.setTrustResolver(trustResolver);
|
||||
assertThat(getRoot()).extracting("trustResolver").isEqualTo(trustResolver);
|
||||
assertThat(getRoot().isAuthenticated()).isTrue();
|
||||
verify(trustResolver).isAuthenticated(explicit);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -117,11 +118,11 @@ public class SecurityEvaluationContextExtensionTests {
|
||||
|
||||
@Test
|
||||
public void setRoleHierarchyWhenNotNullThenVerifyRootObject() {
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT");
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_PARENT");
|
||||
this.securityExtension = new SecurityEvaluationContextExtension(explicit);
|
||||
RoleHierarchy roleHierarchy = new NullRoleHierarchy();
|
||||
RoleHierarchy roleHierarchy = RoleHierarchyImpl.fromHierarchy("ROLE_PARENT > ROLE_EXPLICIT");
|
||||
this.securityExtension.setRoleHierarchy(roleHierarchy);
|
||||
assertThat(getRoot()).extracting("roleHierarchy").isEqualTo(roleHierarchy);
|
||||
assertThat(getRoot().hasRole("EXPLICIT")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,25 +144,25 @@ public class SecurityEvaluationContextExtensionTests {
|
||||
|
||||
@Test
|
||||
public void setDefaultRolePrefixWhenCustomThenVerifyRootObject() {
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT");
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "CUSTOM_EXPLICIT");
|
||||
this.securityExtension = new SecurityEvaluationContextExtension(explicit);
|
||||
String defaultRolePrefix = "CUSTOM_";
|
||||
this.securityExtension.setDefaultRolePrefix(defaultRolePrefix);
|
||||
assertThat(getRoot()).extracting("defaultRolePrefix").isEqualTo(defaultRolePrefix);
|
||||
assertThat(getRoot().hasRole("EXPLICIT")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getRootObjectWhenAdditionalFieldsNotSetThenVerifyDefaults() {
|
||||
TestingAuthenticationToken explicit = new TestingAuthenticationToken("explicit", "password", "ROLE_EXPLICIT");
|
||||
this.securityExtension = new SecurityEvaluationContextExtension(explicit);
|
||||
SecurityExpressionRoot root = getRoot();
|
||||
assertThat(root).extracting("trustResolver").isInstanceOf(AuthenticationTrustResolverImpl.class);
|
||||
assertThat(root).extracting("roleHierarchy").isInstanceOf(NullRoleHierarchy.class);
|
||||
assertThat(root).extracting("permissionEvaluator").isInstanceOf(DenyAllPermissionEvaluator.class);
|
||||
assertThat(root).extracting("defaultRolePrefix").isEqualTo("ROLE_");
|
||||
SecurityExpressionRoot<?> securityExpressionRoot = getRoot();
|
||||
assertThat(securityExpressionRoot.isAuthenticated()).isTrue();
|
||||
assertThat(securityExpressionRoot.hasRole("PARENT")).isFalse();
|
||||
assertThat(securityExpressionRoot.hasRole("EXPLICIT")).isTrue();
|
||||
assertThat(securityExpressionRoot.hasPermission(new Object(), "read")).isFalse();
|
||||
}
|
||||
|
||||
private SecurityExpressionRoot getRoot() {
|
||||
private SecurityExpressionRoot<?> getRoot() {
|
||||
return this.securityExtension.getRootObject();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user