17
17
package org .springframework .security .messaging .context ;
18
18
19
19
import java .lang .annotation .Annotation ;
20
+ import java .util .Map ;
21
+ import java .util .concurrent .ConcurrentHashMap ;
20
22
21
23
import org .springframework .core .MethodParameter ;
22
- import org .springframework .core .annotation .AnnotationUtils ;
23
24
import org .springframework .expression .Expression ;
24
25
import org .springframework .expression .ExpressionParser ;
25
26
import org .springframework .expression .spel .standard .SpelExpressionParser ;
26
27
import org .springframework .expression .spel .support .StandardEvaluationContext ;
27
28
import org .springframework .messaging .Message ;
28
29
import org .springframework .messaging .handler .invocation .HandlerMethodArgumentResolver ;
29
30
import org .springframework .security .core .Authentication ;
31
+ import org .springframework .security .core .annotation .AnnotationSynthesizer ;
32
+ import org .springframework .security .core .annotation .AnnotationSynthesizers ;
33
+ import org .springframework .security .core .annotation .AnnotationTemplateExpressionDefaults ;
30
34
import org .springframework .security .core .annotation .AuthenticationPrincipal ;
31
35
import org .springframework .security .core .context .SecurityContextHolder ;
32
36
import org .springframework .security .core .context .SecurityContextHolderStrategy ;
83
87
* </pre>
84
88
*
85
89
* @author Rob Winch
90
+ * @author DingHao
86
91
* @since 4.0
87
92
*/
88
93
public final class AuthenticationPrincipalArgumentResolver implements HandlerMethodArgumentResolver {
89
94
90
95
private SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder
91
96
.getContextHolderStrategy ();
92
97
98
+ private final Map <MethodParameter , Annotation > cachedAttributes = new ConcurrentHashMap <>();
99
+
93
100
private ExpressionParser parser = new SpelExpressionParser ();
94
101
102
+ private AnnotationSynthesizer <AuthenticationPrincipal > synthesizer = AnnotationSynthesizers
103
+ .requireUnique (AuthenticationPrincipal .class );
104
+
95
105
@ Override
96
106
public boolean supportsParameter (MethodParameter parameter ) {
97
- return findMethodAnnotation (AuthenticationPrincipal . class , parameter ) != null ;
107
+ return findMethodAnnotation (parameter ) != null ;
98
108
}
99
109
100
110
@ Override
@@ -104,7 +114,7 @@ public Object resolveArgument(MethodParameter parameter, Message<?> message) {
104
114
return null ;
105
115
}
106
116
Object principal = authentication .getPrincipal ();
107
- AuthenticationPrincipal authPrincipal = findMethodAnnotation (AuthenticationPrincipal . class , parameter );
117
+ AuthenticationPrincipal authPrincipal = findMethodAnnotation (parameter );
108
118
String expressionToParse = authPrincipal .expression ();
109
119
if (StringUtils .hasLength (expressionToParse )) {
110
120
StandardEvaluationContext context = new StandardEvaluationContext ();
@@ -133,26 +143,29 @@ public void setSecurityContextHolderStrategy(SecurityContextHolderStrategy secur
133
143
this .securityContextHolderStrategy = securityContextHolderStrategy ;
134
144
}
135
145
146
+ /**
147
+ * Configure AuthenticationPrincipal template resolution
148
+ * <p>
149
+ * By default, this value is <code>null</code>, which indicates that templates should
150
+ * not be resolved.
151
+ * @param templateDefaults - whether to resolve AuthenticationPrincipal templates
152
+ * parameters
153
+ * @since 6.4
154
+ */
155
+ public void setTemplateDefaults (AnnotationTemplateExpressionDefaults templateDefaults ) {
156
+ this .synthesizer = AnnotationSynthesizers .requireUnique (AuthenticationPrincipal .class , templateDefaults );
157
+ }
158
+
136
159
/**
137
160
* Obtains the specified {@link Annotation} on the specified {@link MethodParameter}.
138
- * @param annotationClass the class of the {@link Annotation} to find on the
139
161
* {@link MethodParameter}
140
162
* @param parameter the {@link MethodParameter} to search for an {@link Annotation}
141
163
* @return the {@link Annotation} that was found or null.
142
164
*/
143
- private <T extends Annotation > T findMethodAnnotation (Class <T > annotationClass , MethodParameter parameter ) {
144
- T annotation = parameter .getParameterAnnotation (annotationClass );
145
- if (annotation != null ) {
146
- return annotation ;
147
- }
148
- Annotation [] annotationsToSearch = parameter .getParameterAnnotations ();
149
- for (Annotation toSearch : annotationsToSearch ) {
150
- annotation = AnnotationUtils .findAnnotation (toSearch .annotationType (), annotationClass );
151
- if (annotation != null ) {
152
- return annotation ;
153
- }
154
- }
155
- return null ;
165
+ @ SuppressWarnings ("unchecked" )
166
+ private <T extends Annotation > T findMethodAnnotation (MethodParameter parameter ) {
167
+ return (T ) this .cachedAttributes .computeIfAbsent (parameter ,
168
+ (methodParameter ) -> this .synthesizer .synthesize (methodParameter .getParameter ()));
156
169
}
157
170
158
171
}
0 commit comments