Skip to content

Commit e0d676c

Browse files
evgeniychebanjzheaux
authored andcommitted
SecuredAuthorizationManager should cache annotation's value
Closes gh-12232
1 parent 18a3ff2 commit e0d676c

File tree

1 file changed

+28
-20
lines changed

1 file changed

+28
-20
lines changed

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

Lines changed: 28 additions & 20 deletions
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.
@@ -17,14 +17,18 @@
1717
package org.springframework.security.authorization.method;
1818

1919
import java.lang.reflect.Method;
20+
import java.util.Collections;
21+
import java.util.Map;
22+
import java.util.Set;
23+
import java.util.concurrent.ConcurrentHashMap;
2024
import java.util.function.Supplier;
2125

2226
import org.aopalliance.intercept.MethodInvocation;
2327

2428
import org.springframework.aop.support.AopUtils;
25-
import org.springframework.lang.NonNull;
29+
import org.springframework.core.MethodClassKey;
2630
import org.springframework.security.access.annotation.Secured;
27-
import org.springframework.security.authorization.AuthorityAuthorizationManager;
31+
import org.springframework.security.authorization.AuthoritiesAuthorizationManager;
2832
import org.springframework.security.authorization.AuthorizationDecision;
2933
import org.springframework.security.authorization.AuthorizationManager;
3034
import org.springframework.security.core.Authentication;
@@ -39,7 +43,9 @@
3943
*/
4044
public final class SecuredAuthorizationManager implements AuthorizationManager<MethodInvocation> {
4145

42-
private final SecuredAuthorizationManagerRegistry registry = new SecuredAuthorizationManagerRegistry();
46+
private final AuthoritiesAuthorizationManager delegate = new AuthoritiesAuthorizationManager();
47+
48+
private final Map<MethodClassKey, Set<String>> cachedAuthorities = new ConcurrentHashMap<>();
4349

4450
/**
4551
* Determine if an {@link Authentication} has access to a method by evaluating the
@@ -51,26 +57,28 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
5157
*/
5258
@Override
5359
public AuthorizationDecision check(Supplier<Authentication> authentication, MethodInvocation mi) {
54-
AuthorizationManager<MethodInvocation> delegate = this.registry.getManager(mi);
55-
return delegate.check(authentication, mi);
60+
Set<String> authorities = getAuthorities(mi);
61+
return authorities.isEmpty() ? null : this.delegate.check(authentication, authorities);
5662
}
5763

58-
private static final class SecuredAuthorizationManagerRegistry extends AbstractAuthorizationManagerRegistry {
59-
60-
@NonNull
61-
@Override
62-
AuthorizationManager<MethodInvocation> resolveManager(Method method, Class<?> targetClass) {
63-
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
64-
Secured secured = findSecuredAnnotation(specificMethod);
65-
return (secured != null) ? AuthorityAuthorizationManager.hasAnyAuthority(secured.value()) : NULL_MANAGER;
66-
}
64+
private Set<String> getAuthorities(MethodInvocation methodInvocation) {
65+
Method method = methodInvocation.getMethod();
66+
Object target = methodInvocation.getThis();
67+
Class<?> targetClass = (target != null) ? target.getClass() : null;
68+
MethodClassKey cacheKey = new MethodClassKey(method, targetClass);
69+
return this.cachedAuthorities.computeIfAbsent(cacheKey, (k) -> resolveAuthorities(method, targetClass));
70+
}
6771

68-
private Secured findSecuredAnnotation(Method method) {
69-
Secured secured = AuthorizationAnnotationUtils.findUniqueAnnotation(method, Secured.class);
70-
return (secured != null) ? secured
71-
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), Secured.class);
72-
}
72+
private Set<String> resolveAuthorities(Method method, Class<?> targetClass) {
73+
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
74+
Secured secured = findSecuredAnnotation(specificMethod);
75+
return (secured != null) ? Set.of(secured.value()) : Collections.emptySet();
76+
}
7377

78+
private Secured findSecuredAnnotation(Method method) {
79+
Secured secured = AuthorizationAnnotationUtils.findUniqueAnnotation(method, Secured.class);
80+
return (secured != null) ? secured
81+
: AuthorizationAnnotationUtils.findUniqueAnnotation(method.getDeclaringClass(), Secured.class);
7482
}
7583

7684
}

0 commit comments

Comments
 (0)