Skip to content

Commit 782b792

Browse files
evgeniychebanjzheaux
authored andcommitted
SecuredAuthorizationManager should allow customizing underlying authorization manager
Closes gh-12233
1 parent d84b8d2 commit 782b792

File tree

2 files changed

+44
-3
lines changed

2 files changed

+44
-3
lines changed

core/src/main/java/org/springframework/security/authorization/method/SecuredAuthorizationManager.java

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.security.authorization.method;
1818

1919
import java.lang.reflect.Method;
20+
import java.util.Collection;
2021
import java.util.Collections;
2122
import java.util.Map;
2223
import java.util.Set;
@@ -32,6 +33,7 @@
3233
import org.springframework.security.authorization.AuthorizationDecision;
3334
import org.springframework.security.authorization.AuthorizationManager;
3435
import org.springframework.security.core.Authentication;
36+
import org.springframework.util.Assert;
3537

3638
/**
3739
* An {@link AuthorizationManager} which can determine if an {@link Authentication} may
@@ -43,10 +45,23 @@
4345
*/
4446
public final class SecuredAuthorizationManager implements AuthorizationManager<MethodInvocation> {
4547

46-
private final AuthoritiesAuthorizationManager delegate = new AuthoritiesAuthorizationManager();
48+
private AuthorizationManager<Collection<String>> authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
4749

4850
private final Map<MethodClassKey, Set<String>> cachedAuthorities = new ConcurrentHashMap<>();
4951

52+
/**
53+
* Sets an {@link AuthorizationManager} that accepts a collection of authority
54+
* strings.
55+
* @param authoritiesAuthorizationManager the {@link AuthorizationManager} that
56+
* accepts a collection of authority strings to use
57+
* @since 6.1
58+
*/
59+
public void setAuthoritiesAuthorizationManager(
60+
AuthorizationManager<Collection<String>> authoritiesAuthorizationManager) {
61+
Assert.notNull(authoritiesAuthorizationManager, "authoritiesAuthorizationManager cannot be null");
62+
this.authoritiesAuthorizationManager = authoritiesAuthorizationManager;
63+
}
64+
5065
/**
5166
* Determine if an {@link Authentication} has access to a method by evaluating the
5267
* {@link Secured} annotation that {@link MethodInvocation} specifies.
@@ -58,7 +73,7 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
5873
@Override
5974
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
6075
Set<String> authorities = getAuthorities(mi);
61-
return authorities.isEmpty() ? null : this.delegate.check(authentication, authorities);
76+
return authorities.isEmpty() ? null : this.authoritiesAuthorizationManager.check(authentication, authorities);
6277
}
6378

6479
private Set<String> getAuthorities(MethodInvocation methodInvocation) {

core/src/test/java/org/springframework/security/authorization/method/SecuredAuthorizationManagerTests.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2021 the original author or authors.
2+
* Copyright 2002-2023 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -18,6 +18,8 @@
1818

1919
import java.lang.annotation.Retention;
2020
import java.lang.annotation.RetentionPolicy;
21+
import java.util.Collection;
22+
import java.util.Set;
2123
import java.util.function.Supplier;
2224

2325
import org.junit.jupiter.api.Test;
@@ -29,10 +31,14 @@
2931
import org.springframework.security.authentication.TestAuthentication;
3032
import org.springframework.security.authentication.TestingAuthenticationToken;
3133
import org.springframework.security.authorization.AuthorizationDecision;
34+
import org.springframework.security.authorization.AuthorizationManager;
3235
import org.springframework.security.core.Authentication;
3336

3437
import static org.assertj.core.api.Assertions.assertThat;
3538
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
39+
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
40+
import static org.mockito.Mockito.mock;
41+
import static org.mockito.Mockito.verify;
3642

3743
/**
3844
* Tests for {@link SecuredAuthorizationManager}.
@@ -41,6 +47,26 @@
4147
*/
4248
public class SecuredAuthorizationManagerTests {
4349

50+
@Test
51+
public void setAuthoritiesAuthorizationManagerWhenNullThenException() {
52+
SecuredAuthorizationManager manager = new SecuredAuthorizationManager();
53+
assertThatIllegalArgumentException().isThrownBy(() -> manager.setAuthoritiesAuthorizationManager(null))
54+
.withMessage("authoritiesAuthorizationManager cannot be null");
55+
}
56+
57+
@Test
58+
public void setAuthoritiesAuthorizationManagerWhenNotNullThenVerifyUsage() throws Exception {
59+
AuthorizationManager<Collection<String>> authoritiesAuthorizationManager = mock(AuthorizationManager.class);
60+
SecuredAuthorizationManager manager = new SecuredAuthorizationManager();
61+
manager.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
62+
MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class,
63+
"securedUserOrAdmin");
64+
Supplier<Authentication> authentication = TestAuthentication::authenticatedUser;
65+
AuthorizationDecision decision = manager.check(authentication, methodInvocation);
66+
assertThat(decision).isNull();
67+
verify(authoritiesAuthorizationManager).check(authentication, Set.of("ROLE_USER", "ROLE_ADMIN"));
68+
}
69+
4470
@Test
4571
public void checkDoSomethingWhenNoSecuredAnnotationThenNullDecision() throws Exception {
4672
MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class,

0 commit comments

Comments
 (0)