mirror of
https://github.com/spring-projects/spring-security.git
synced 2025-05-31 01:02:14 +00:00
Fix allOf/anyOf Abstain Logic
Closes gh-13069
This commit is contained in:
parent
744b74f4c9
commit
9244989b2e
@ -41,11 +41,17 @@ public final class AuthorizationManagers {
|
|||||||
List<AuthorizationDecision> decisions = new ArrayList<>();
|
List<AuthorizationDecision> decisions = new ArrayList<>();
|
||||||
for (AuthorizationManager<T> manager : managers) {
|
for (AuthorizationManager<T> manager : managers) {
|
||||||
AuthorizationDecision decision = manager.check(authentication, object);
|
AuthorizationDecision decision = manager.check(authentication, object);
|
||||||
if (decision == null || decision.isGranted()) {
|
if (decision == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (decision.isGranted()) {
|
||||||
return decision;
|
return decision;
|
||||||
}
|
}
|
||||||
decisions.add(decision);
|
decisions.add(decision);
|
||||||
}
|
}
|
||||||
|
if (decisions.isEmpty()) {
|
||||||
|
return new AuthorizationDecision(false);
|
||||||
|
}
|
||||||
return new CompositeAuthorizationDecision(false, decisions);
|
return new CompositeAuthorizationDecision(false, decisions);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -64,11 +70,17 @@ public final class AuthorizationManagers {
|
|||||||
List<AuthorizationDecision> decisions = new ArrayList<>();
|
List<AuthorizationDecision> decisions = new ArrayList<>();
|
||||||
for (AuthorizationManager<T> manager : managers) {
|
for (AuthorizationManager<T> manager : managers) {
|
||||||
AuthorizationDecision decision = manager.check(authentication, object);
|
AuthorizationDecision decision = manager.check(authentication, object);
|
||||||
if (decision != null && !decision.isGranted()) {
|
if (decision == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!decision.isGranted()) {
|
||||||
return decision;
|
return decision;
|
||||||
}
|
}
|
||||||
decisions.add(decision);
|
decisions.add(decision);
|
||||||
}
|
}
|
||||||
|
if (decisions.isEmpty()) {
|
||||||
|
return new AuthorizationDecision(true);
|
||||||
|
}
|
||||||
return new CompositeAuthorizationDecision(true, decisions);
|
return new CompositeAuthorizationDecision(true, decisions);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -36,12 +36,14 @@ class AuthorizationManagersTests {
|
|||||||
assertThat(decision.isGranted()).isTrue();
|
assertThat(decision.isGranted()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-13069
|
||||||
@Test
|
@Test
|
||||||
void checkAnyOfWhenOneAbstainedThenAbstainedDecision() {
|
void checkAnyOfWhenAllNonAbstainingDeniesThenDeniedDecision() {
|
||||||
AuthorizationManager<?> composed = AuthorizationManagers.anyOf((a, o) -> new AuthorizationDecision(false),
|
AuthorizationManager<?> composed = AuthorizationManagers.anyOf((a, o) -> new AuthorizationDecision(false),
|
||||||
(a, o) -> null);
|
(a, o) -> null);
|
||||||
AuthorizationDecision decision = composed.check(null, null);
|
AuthorizationDecision decision = composed.check(null, null);
|
||||||
assertThat(decision).isNull();
|
assertThat(decision).isNotNull();
|
||||||
|
assertThat(decision.isGranted()).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@ -61,8 +63,9 @@ class AuthorizationManagersTests {
|
|||||||
assertThat(decision.isGranted()).isTrue();
|
assertThat(decision.isGranted()).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// gh-13069
|
||||||
@Test
|
@Test
|
||||||
void checkAllOfWhenOneAbstainedThenGrantedDecision() {
|
void checkAllOfWhenAllNonAbstainingGrantsThenGrantedDecision() {
|
||||||
AuthorizationManager<?> composed = AuthorizationManagers.allOf((a, o) -> new AuthorizationDecision(true),
|
AuthorizationManager<?> composed = AuthorizationManagers.allOf((a, o) -> new AuthorizationDecision(true),
|
||||||
(a, o) -> null);
|
(a, o) -> null);
|
||||||
AuthorizationDecision decision = composed.check(null, null);
|
AuthorizationDecision decision = composed.check(null, null);
|
||||||
|
@ -278,6 +278,10 @@ Read on to find the best match for your situation.
|
|||||||
If your application uses {security-api-url}org/springframework/security/access/vote/UnanimousBased.html[`UnanimousBased`] with the default voters, you likely need do nothing since unanimous-based is the default behavior with {security-api-url}org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.html[`@EnableMethodSecurity`].
|
If your application uses {security-api-url}org/springframework/security/access/vote/UnanimousBased.html[`UnanimousBased`] with the default voters, you likely need do nothing since unanimous-based is the default behavior with {security-api-url}org/springframework/security/config/annotation/method/configuration/EnableMethodSecurity.html[`@EnableMethodSecurity`].
|
||||||
|
|
||||||
However, if you do discover that you cannot accept the default authorization managers, you can use `AuthorizationManagers.allOf` to compose your own arrangement.
|
However, if you do discover that you cannot accept the default authorization managers, you can use `AuthorizationManagers.allOf` to compose your own arrangement.
|
||||||
|
|
||||||
|
Note that there is a difference with `allOf`, which is that if all delegates abstain then it grants authorization.
|
||||||
|
If you must deny authorization when all delegates abstain, please implement a composite {security-api-url}org/springframework/security/authorization/AuthorizationManager.html[`AuthorizationManager`] that takes the set of delegate ``AuthorizationManager``s into account.
|
||||||
|
|
||||||
Having done that, please follow the details in the reference manual for xref:servlet/authorization/method-security.adoc#jc-method-security-custom-authorization-manager[adding a custom `AuthorizationManager`].
|
Having done that, please follow the details in the reference manual for xref:servlet/authorization/method-security.adoc#jc-method-security-custom-authorization-manager[adding a custom `AuthorizationManager`].
|
||||||
|
|
||||||
==== I use `AffirmativeBased`
|
==== I use `AffirmativeBased`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user