1
1
/*
2
- * Copyright 2002-2021 the original author or authors.
2
+ * Copyright 2002-2023 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
package org .springframework .security .authorization .method ;
18
18
19
19
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 ;
20
24
import java .util .function .Supplier ;
21
25
22
26
import org .aopalliance .intercept .MethodInvocation ;
23
27
24
28
import org .springframework .aop .support .AopUtils ;
25
- import org .springframework .lang . NonNull ;
29
+ import org .springframework .core . MethodClassKey ;
26
30
import org .springframework .security .access .annotation .Secured ;
27
- import org .springframework .security .authorization .AuthorityAuthorizationManager ;
31
+ import org .springframework .security .authorization .AuthoritiesAuthorizationManager ;
28
32
import org .springframework .security .authorization .AuthorizationDecision ;
29
33
import org .springframework .security .authorization .AuthorizationManager ;
30
34
import org .springframework .security .core .Authentication ;
39
43
*/
40
44
public final class SecuredAuthorizationManager implements AuthorizationManager <MethodInvocation > {
41
45
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 <>();
43
49
44
50
/**
45
51
* Determine if an {@link Authentication} has access to a method by evaluating the
@@ -51,26 +57,28 @@ public final class SecuredAuthorizationManager implements AuthorizationManager<M
51
57
*/
52
58
@ Override
53
59
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 );
56
62
}
57
63
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
+ }
67
71
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
+ }
73
77
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 );
74
82
}
75
83
76
84
}
0 commit comments