Skip to content

Commit c2ec5a0

Browse files
committed
Inject AuthorizationManagerFactory into DefaultMethodSecurityExpressionHandler
Signed-off-by: Steve Riesenberg <[email protected]>
1 parent 03a6d80 commit c2ec5a0

File tree

6 files changed

+296
-39
lines changed

6 files changed

+296
-39
lines changed

config/src/main/java/org/springframework/security/config/annotation/method/configuration/PrePostMethodSecurityConfiguration.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import org.springframework.security.aot.hint.SecurityHintsRegistrar;
4040
import org.springframework.security.authorization.AuthorizationEventPublisher;
4141
import org.springframework.security.authorization.AuthorizationManager;
42+
import org.springframework.security.authorization.AuthorizationManagerFactory;
4243
import org.springframework.security.authorization.method.AuthorizationManagerAfterMethodInterceptor;
4344
import org.springframework.security.authorization.method.AuthorizationManagerBeforeMethodInterceptor;
4445
import org.springframework.security.authorization.method.MethodInvocationResult;
@@ -121,6 +122,11 @@ void setRoleHierarchy(RoleHierarchy roleHierarchy) {
121122
this.expressionHandler.setRoleHierarchy(roleHierarchy);
122123
}
123124

125+
@Autowired(required = false)
126+
void setAuthorizationManagerFactory(AuthorizationManagerFactory<MethodInvocation> authorizationManagerFactory) {
127+
this.expressionHandler.setAuthorizationManagerFactory(authorizationManagerFactory);
128+
}
129+
124130
@Autowired(required = false)
125131
void setTemplateDefaults(AnnotationTemplateExpressionDefaults templateDefaults) {
126132
this.preFilterMethodInterceptor.setTemplateDefaults(templateDefaults);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
/*
2+
* Copyright 2002-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.security.access.expression.method;
18+
19+
import org.aopalliance.intercept.MethodInvocation;
20+
21+
import org.springframework.security.access.hierarchicalroles.NullRoleHierarchy;
22+
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
23+
import org.springframework.security.authentication.AuthenticationTrustResolver;
24+
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
25+
import org.springframework.security.authorization.AuthenticatedAuthorizationManager;
26+
import org.springframework.security.authorization.AuthorityAuthorizationManager;
27+
import org.springframework.security.authorization.AuthorizationManager;
28+
import org.springframework.security.authorization.AuthorizationManagerFactory;
29+
30+
/**
31+
* A factory for creating {@link AuthorizationManager} instances for method security.
32+
*
33+
* @author Steve Riesenberg
34+
* @since 7.0
35+
*/
36+
final class DefaultMethodSecurityAuthorizationManagerFactory implements AuthorizationManagerFactory<MethodInvocation> {
37+
38+
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
39+
40+
private RoleHierarchy roleHierarchy = new NullRoleHierarchy();
41+
42+
private String rolePrefix = "ROLE_";
43+
44+
AuthenticationTrustResolver getTrustResolver() {
45+
return this.trustResolver;
46+
}
47+
48+
void setTrustResolver(AuthenticationTrustResolver trustResolver) {
49+
this.trustResolver = trustResolver;
50+
}
51+
52+
RoleHierarchy getRoleHierarchy() {
53+
return this.roleHierarchy;
54+
}
55+
56+
void setRoleHierarchy(RoleHierarchy roleHierarchy) {
57+
this.roleHierarchy = roleHierarchy;
58+
}
59+
60+
String getRolePrefix() {
61+
return this.rolePrefix;
62+
}
63+
64+
void setRolePrefix(String rolePrefix) {
65+
this.rolePrefix = rolePrefix;
66+
}
67+
68+
@Override
69+
public AuthorizationManager<MethodInvocation> hasRole(String role) {
70+
return hasAnyRole(role);
71+
}
72+
73+
@Override
74+
public AuthorizationManager<MethodInvocation> hasAnyRole(String... roles) {
75+
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyRole(this.rolePrefix, roles));
76+
}
77+
78+
@Override
79+
public AuthorizationManager<MethodInvocation> hasAuthority(String authority) {
80+
return withRoleHierarchy(AuthorityAuthorizationManager.hasAuthority(authority));
81+
}
82+
83+
@Override
84+
public AuthorizationManager<MethodInvocation> hasAnyAuthority(String... authorities) {
85+
return withRoleHierarchy(AuthorityAuthorizationManager.hasAnyAuthority(authorities));
86+
}
87+
88+
@Override
89+
public AuthorizationManager<MethodInvocation> authenticated() {
90+
return withTrustResolver(AuthenticatedAuthorizationManager.authenticated());
91+
}
92+
93+
@Override
94+
public AuthorizationManager<MethodInvocation> fullyAuthenticated() {
95+
return withTrustResolver(AuthenticatedAuthorizationManager.fullyAuthenticated());
96+
}
97+
98+
@Override
99+
public AuthorizationManager<MethodInvocation> rememberMe() {
100+
return withTrustResolver(AuthenticatedAuthorizationManager.rememberMe());
101+
}
102+
103+
@Override
104+
public AuthorizationManager<MethodInvocation> anonymous() {
105+
return withTrustResolver(AuthenticatedAuthorizationManager.anonymous());
106+
}
107+
108+
private AuthorityAuthorizationManager<MethodInvocation> withRoleHierarchy(
109+
AuthorityAuthorizationManager<MethodInvocation> authorizationManager) {
110+
authorizationManager.setRoleHierarchy(this.roleHierarchy);
111+
return authorizationManager;
112+
}
113+
114+
private AuthenticatedAuthorizationManager<MethodInvocation> withTrustResolver(
115+
AuthenticatedAuthorizationManager<MethodInvocation> authorizationManager) {
116+
authorizationManager.setTrustResolver(this.trustResolver);
117+
return authorizationManager;
118+
}
119+
120+
}

core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@
4141
import org.springframework.security.access.PermissionCacheOptimizer;
4242
import org.springframework.security.access.expression.AbstractSecurityExpressionHandler;
4343
import org.springframework.security.access.expression.ExpressionUtils;
44+
import org.springframework.security.access.hierarchicalroles.RoleHierarchy;
4445
import org.springframework.security.authentication.AuthenticationTrustResolver;
4546
import org.springframework.security.authentication.AuthenticationTrustResolverImpl;
47+
import org.springframework.security.authorization.AuthorizationManagerFactory;
4648
import org.springframework.security.core.Authentication;
4749
import org.springframework.security.core.parameters.DefaultSecurityParameterNameDiscoverer;
4850
import org.springframework.util.Assert;
@@ -63,14 +65,14 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
6365

6466
protected final Log logger = LogFactory.getLog(getClass());
6567

66-
private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl();
68+
private final DefaultMethodSecurityAuthorizationManagerFactory defaultAuthorizationManagerFactory = new DefaultMethodSecurityAuthorizationManagerFactory();
69+
70+
private AuthorizationManagerFactory<MethodInvocation> authorizationManagerFactory = defaultAuthorizationManagerFactory;
6771

6872
private ParameterNameDiscoverer parameterNameDiscoverer = new DefaultSecurityParameterNameDiscoverer();
6973

7074
private @Nullable PermissionCacheOptimizer permissionCacheOptimizer = null;
7175

72-
private String defaultRolePrefix = "ROLE_";
73-
7476
public DefaultMethodSecurityExpressionHandler() {
7577
}
7678

@@ -103,12 +105,10 @@ protected MethodSecurityExpressionOperations createSecurityExpressionRoot(Authen
103105

104106
private MethodSecurityExpressionOperations createSecurityExpressionRoot(Supplier<Authentication> authentication,
105107
MethodInvocation invocation) {
106-
MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication);
107-
root.setThis(invocation.getThis());
108+
MethodSecurityExpressionRoot root = new MethodSecurityExpressionRoot(authentication, invocation);
109+
root.setAuthorizationManagerFactory(this.authorizationManagerFactory);
108110
root.setPermissionEvaluator(getPermissionEvaluator());
109-
root.setTrustResolver(getTrustResolver());
110-
Optional.ofNullable(getRoleHierarchy()).ifPresent(root::setRoleHierarchy);
111-
root.setDefaultRolePrefix(getDefaultRolePrefix());
111+
root.setThis(invocation.getThis());
112112
return root;
113113
}
114114

@@ -224,6 +224,19 @@ private Object filterStream(final Stream<?> filterTarget, Expression filterExpre
224224
}).onClose(filterTarget::close);
225225
}
226226

227+
/**
228+
* Sets the {@link AuthorizationManagerFactory} to be used. The default is
229+
* {@link DefaultMethodSecurityAuthorizationManagerFactory}.
230+
* @param authorizationManagerFactory the {@link AuthorizationManagerFactory} to use.
231+
* Cannot be null.
232+
* @since 7.0
233+
*/
234+
public void setAuthorizationManagerFactory(
235+
AuthorizationManagerFactory<MethodInvocation> authorizationManagerFactory) {
236+
Assert.notNull(authorizationManagerFactory, "authorizationManagerFactory cannot be null");
237+
this.authorizationManagerFactory = authorizationManagerFactory;
238+
}
239+
227240
/**
228241
* Sets the {@link AuthenticationTrustResolver} to be used. The default is
229242
* {@link AuthenticationTrustResolverImpl}.
@@ -232,14 +245,26 @@ private Object filterStream(final Stream<?> filterTarget, Expression filterExpre
232245
*/
233246
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
234247
Assert.notNull(trustResolver, "trustResolver cannot be null");
235-
this.trustResolver = trustResolver;
248+
this.defaultAuthorizationManagerFactory.setTrustResolver(trustResolver);
236249
}
237250

238251
/**
239252
* @return The current {@link AuthenticationTrustResolver}
240253
*/
241254
protected AuthenticationTrustResolver getTrustResolver() {
242-
return this.trustResolver;
255+
return this.defaultAuthorizationManagerFactory.getTrustResolver();
256+
}
257+
258+
@Override
259+
public void setRoleHierarchy(@Nullable RoleHierarchy roleHierarchy) {
260+
if (roleHierarchy != null) {
261+
this.defaultAuthorizationManagerFactory.setRoleHierarchy(roleHierarchy);
262+
}
263+
}
264+
265+
@Override
266+
protected @Nullable RoleHierarchy getRoleHierarchy() {
267+
return this.defaultAuthorizationManagerFactory.getRoleHierarchy();
243268
}
244269

245270
/**
@@ -288,14 +313,14 @@ public void setReturnObject(@Nullable Object returnObject, EvaluationContext ctx
288313
* @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
289314
*/
290315
public void setDefaultRolePrefix(String defaultRolePrefix) {
291-
this.defaultRolePrefix = defaultRolePrefix;
316+
this.defaultAuthorizationManagerFactory.setRolePrefix(defaultRolePrefix);
292317
}
293318

294319
/**
295320
* @return The default role prefix
296321
*/
297322
protected String getDefaultRolePrefix() {
298-
return this.defaultRolePrefix;
323+
return this.defaultAuthorizationManagerFactory.getRolePrefix();
299324
}
300325

301326
}

0 commit comments

Comments
 (0)