Skip to content

Commit fa2bc74

Browse files
kandaguru17jzheaux
authored andcommitted
Use AuthoritiesAuthorizationManager in Jsr250AuthorizationManager
Closes gh-12782
1 parent 208fb62 commit fa2bc74

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

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

+28-6
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,7 @@
1818

1919
import java.lang.annotation.Annotation;
2020
import java.lang.reflect.Method;
21+
import java.util.Collection;
2122
import java.util.HashSet;
2223
import java.util.Set;
2324
import java.util.function.Supplier;
@@ -30,7 +31,7 @@
3031
import org.springframework.aop.support.AopUtils;
3132
import org.springframework.core.annotation.AnnotationConfigurationException;
3233
import org.springframework.lang.NonNull;
33-
import org.springframework.security.authorization.AuthorityAuthorizationManager;
34+
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
3435
import org.springframework.security.authorization.AuthorizationDecision;
3536
import org.springframework.security.authorization.AuthorizationManager;
3637
import org.springframework.security.core.Authentication;
@@ -57,8 +58,23 @@ public final class Jsr250AuthorizationManager implements AuthorizationManager<Me
5758

5859
private final Jsr250AuthorizationManagerRegistry registry = new Jsr250AuthorizationManagerRegistry();
5960

61+
private AuthorizationManager<Collection<String>> authoritiesAuthorizationManager = new AuthoritiesAuthorizationManager();
62+
6063
private String rolePrefix = "ROLE_";
6164

65+
/**
66+
* Sets an {@link AuthorizationManager} that accepts a collection of authority
67+
* strings.
68+
* @param authoritiesAuthorizationManager the {@link AuthorizationManager} that
69+
* accepts a collection of authority strings to use
70+
* @since 6.1
71+
*/
72+
public void setAuthoritiesAuthorizationManager(
73+
AuthorizationManager<Collection<String>> authoritiesAuthorizationManager) {
74+
Assert.notNull(authoritiesAuthorizationManager, "authoritiesAuthorizationManager cannot be null");
75+
this.authoritiesAuthorizationManager = authoritiesAuthorizationManager;
76+
}
77+
6278
/**
6379
* Sets the role prefix. Defaults to "ROLE_".
6480
* @param rolePrefix the role prefix to use
@@ -95,10 +111,8 @@ AuthorizationManager<MethodInvocation> resolveManager(Method method, Class<?> ta
95111
if (annotation instanceof PermitAll) {
96112
return (a, o) -> new AuthorizationDecision(true);
97113
}
98-
if (annotation instanceof RolesAllowed) {
99-
RolesAllowed rolesAllowed = (RolesAllowed) annotation;
100-
return AuthorityAuthorizationManager.hasAnyRole(Jsr250AuthorizationManager.this.rolePrefix,
101-
rolesAllowed.value());
114+
if (annotation instanceof RolesAllowed rolesAllowed) {
115+
return (a, o) -> Jsr250AuthorizationManager.this.authoritiesAuthorizationManager.check(a, getAllowedRolesWithPrefix(rolesAllowed));
102116
}
103117
return NULL_MANAGER;
104118
}
@@ -145,6 +159,14 @@ private Annotation findAnnotation(Class<?> clazz) {
145159
return annotations.iterator().next();
146160
}
147161

162+
private Set<String> getAllowedRolesWithPrefix(RolesAllowed rolesAllowed) {
163+
Set<String> roles = new HashSet<>();
164+
for (int i = 0; i < rolesAllowed.value().length; i++) {
165+
roles.add(Jsr250AuthorizationManager.this.rolePrefix + rolesAllowed.value()[i]);
166+
}
167+
return roles;
168+
}
169+
148170
}
149171

150172
}

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

+54-2
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 jakarta.annotation.security.DenyAll;
@@ -30,11 +32,14 @@
3032
import org.springframework.security.authentication.TestAuthentication;
3133
import org.springframework.security.authentication.TestingAuthenticationToken;
3234
import org.springframework.security.authorization.AuthorizationDecision;
35+
import org.springframework.security.authorization.AuthorizationManager;
3336
import org.springframework.security.core.Authentication;
3437

3538
import static org.assertj.core.api.Assertions.assertThat;
3639
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
3740
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
41+
import static org.mockito.Mockito.mock;
42+
import static org.mockito.Mockito.verify;
3843

3944
/**
4045
* Tests for {@link Jsr250AuthorizationManager}.
@@ -63,6 +68,27 @@ public void setRolePrefixWhenNotNullThenSets() {
6368
assertThat(manager).extracting("rolePrefix").isEqualTo("CUSTOM_");
6469
}
6570

71+
@Test
72+
public void setAuthoritiesAuthorizationManagerWhenNullThenException() {
73+
Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager();
74+
assertThatIllegalArgumentException().isThrownBy(() -> manager.setAuthoritiesAuthorizationManager(null))
75+
.withMessage("authoritiesAuthorizationManager cannot be null");
76+
}
77+
78+
@Test
79+
public void setAuthoritiesAuthorizationManagerWhenNotNullThenVerifyUsage() throws Exception {
80+
AuthorizationManager<Collection<String>> authoritiesAuthorizationManager = mock(AuthorizationManager.class);
81+
Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager();
82+
manager.setAuthoritiesAuthorizationManager(authoritiesAuthorizationManager);
83+
MockMethodInvocation methodInvocation = new MockMethodInvocation(new ClassLevelAnnotations(),
84+
ClassLevelAnnotations.class, "rolesAllowedAdmin");
85+
Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password",
86+
"ROLE_ADMIN");
87+
AuthorizationDecision decision = manager.check(authentication, methodInvocation);
88+
assertThat(decision).isNull();
89+
verify(authoritiesAuthorizationManager).check(authentication, Set.of("ROLE_ADMIN"));
90+
}
91+
6692
@Test
6793
public void checkDoSomethingWhenNoJsr250AnnotationsThenNullDecision() throws Exception {
6894
MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class,
@@ -123,7 +149,7 @@ public void checkRolesAllowedUserOrAdminWhenRoleAnonymousThenDeniedDecision() th
123149
}
124150

125151
@Test
126-
public void checkMultipleAnnotationsWhenInvokedThenAnnotationConfigurationException() throws Exception {
152+
public void checkMultipleMethodAnnotationsWhenInvokedThenAnnotationConfigurationException() throws Exception {
127153
Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password",
128154
"ROLE_ANONYMOUS");
129155
MockMethodInvocation methodInvocation = new MockMethodInvocation(new TestClass(), TestClass.class,
@@ -133,6 +159,16 @@ public void checkMultipleAnnotationsWhenInvokedThenAnnotationConfigurationExcept
133159
.isThrownBy(() -> manager.check(authentication, methodInvocation));
134160
}
135161

162+
@Test
163+
public void checkMultipleClassAnnotationsWhenInvokedThenAnnotationConfigurationException() throws Exception {
164+
Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "ROLE_USER");
165+
MockMethodInvocation methodInvocation = new MockMethodInvocation(new ClassLevelIllegalAnnotations(),
166+
ClassLevelIllegalAnnotations.class, "inheritedAnnotations");
167+
Jsr250AuthorizationManager manager = new Jsr250AuthorizationManager();
168+
assertThatExceptionOfType(AnnotationConfigurationException.class)
169+
.isThrownBy(() -> manager.check(authentication, methodInvocation));
170+
}
171+
136172
@Test
137173
public void checkRequiresAdminWhenClassAnnotationsThenMethodAnnotationsTakePrecedence() throws Exception {
138174
Supplier<Authentication> authentication = () -> new TestingAuthenticationToken("user", "password", "ROLE_USER");
@@ -247,6 +283,15 @@ public void inheritedAnnotations() {
247283

248284
}
249285

286+
@MyIllegalRolesAllowed
287+
public static class ClassLevelIllegalAnnotations {
288+
289+
public void inheritedAnnotations() {
290+
291+
}
292+
293+
}
294+
250295
public interface InterfaceAnnotationsOne {
251296

252297
@RolesAllowed("ADMIN")
@@ -274,4 +319,11 @@ public interface InterfaceAnnotationsThree {
274319

275320
}
276321

322+
@DenyAll
323+
@RolesAllowed("USER")
324+
@Retention(RetentionPolicy.RUNTIME)
325+
public @interface MyIllegalRolesAllowed {
326+
327+
}
328+
277329
}

0 commit comments

Comments
 (0)