Skip to content

Commit 2cea5f9

Browse files
committed
Add AuthorizationManagerSecurityExpressionRoot
Signed-off-by: Steve Riesenberg <[email protected]>
1 parent 8425f56 commit 2cea5f9

File tree

3 files changed

+206
-127
lines changed

3 files changed

+206
-127
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
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;
18+
19+
import java.io.Serializable;
20+
import java.util.function.Supplier;
21+
22+
import org.jspecify.annotations.Nullable;
23+
24+
import org.springframework.security.access.PermissionEvaluator;
25+
import org.springframework.security.authorization.AuthorizationManager;
26+
import org.springframework.security.authorization.AuthorizationManagerFactory;
27+
import org.springframework.security.authorization.AuthorizationResult;
28+
import org.springframework.security.authorization.DefaultAuthorizationManagerFactory;
29+
import org.springframework.security.core.Authentication;
30+
import org.springframework.util.Assert;
31+
import org.springframework.util.function.SingletonSupplier;
32+
33+
/**
34+
* A security expression root object that delegates to {@link AuthorizationManager}
35+
* instances.
36+
*
37+
* @param <T> the type of object that the authorization check is being done on
38+
* @author Steve Riesenberg
39+
* @since 7.0
40+
*/
41+
public class AuthorizationManagerSecurityExpressionRoot<T> implements SecurityExpressionOperations {
42+
43+
private static final DefaultAuthorizationManagerFactory<?> DEFAULT_AUTHORIZATION_MANAGER_FACTORY = new DefaultAuthorizationManagerFactory<>();
44+
45+
private static final PermissionEvaluator DEFAULT_PERMISSION_EVALUATOR = new DenyAllPermissionEvaluator();
46+
47+
private final Supplier<Authentication> authentication;
48+
49+
private final T object;
50+
51+
private AuthorizationManagerFactory<T> authorizationManagerFactory = defaultAuthorizationManagerFactory();
52+
53+
private PermissionEvaluator permissionEvaluator = DEFAULT_PERMISSION_EVALUATOR;
54+
55+
public final boolean permitAll = true;
56+
57+
public final boolean denyAll = false;
58+
59+
public final String read = "read";
60+
61+
public final String write = "write";
62+
63+
public final String create = "create";
64+
65+
public final String delete = "delete";
66+
67+
public final String admin = "administration";
68+
69+
/**
70+
* Creates a new instance.
71+
* @param authentication the {@link Authentication} to use. Cannot be null.
72+
* @param object the object that the authorization check is being done on
73+
*/
74+
public AuthorizationManagerSecurityExpressionRoot(Supplier<Authentication> authentication, T object) {
75+
this.authentication = SingletonSupplier.of(() -> {
76+
Authentication value = authentication.get();
77+
Assert.notNull(value, "Authentication object cannot be null");
78+
return value;
79+
});
80+
this.object = object;
81+
}
82+
83+
@Override
84+
public boolean permitAll() {
85+
return isGranted(this.authorizationManagerFactory.permitAll());
86+
}
87+
88+
@Override
89+
public boolean denyAll() {
90+
return isGranted(this.authorizationManagerFactory.denyAll());
91+
}
92+
93+
@Override
94+
public boolean hasRole(String role) {
95+
return isGranted(this.authorizationManagerFactory.hasRole(role));
96+
}
97+
98+
@Override
99+
public boolean hasAnyRole(String... roles) {
100+
return isGranted(this.authorizationManagerFactory.hasAnyRole(roles));
101+
}
102+
103+
@Override
104+
public boolean hasAuthority(String authority) {
105+
return isGranted(this.authorizationManagerFactory.hasAuthority(authority));
106+
}
107+
108+
@Override
109+
public boolean hasAnyAuthority(String... authorities) {
110+
return isGranted(this.authorizationManagerFactory.hasAnyAuthority(authorities));
111+
}
112+
113+
@Override
114+
public boolean isAnonymous() {
115+
return isGranted(this.authorizationManagerFactory.anonymous());
116+
}
117+
118+
@Override
119+
public boolean isAuthenticated() {
120+
return isGranted(this.authorizationManagerFactory.authenticated());
121+
}
122+
123+
@Override
124+
public boolean isRememberMe() {
125+
return isGranted(this.authorizationManagerFactory.rememberMe());
126+
}
127+
128+
@Override
129+
public boolean isFullyAuthenticated() {
130+
return isGranted(this.authorizationManagerFactory.fullyAuthenticated());
131+
}
132+
133+
private boolean isGranted(AuthorizationManager<T> authorizationManager) {
134+
AuthorizationResult authorizationResult = authorizationManager.authorize(this.authentication, this.object);
135+
return (authorizationResult != null && authorizationResult.isGranted());
136+
}
137+
138+
@Override
139+
public boolean hasPermission(Object target, Object permission) {
140+
return this.permissionEvaluator.hasPermission(getAuthentication(), target, permission);
141+
}
142+
143+
@Override
144+
public boolean hasPermission(Object targetId, String targetType, Object permission) {
145+
return this.permissionEvaluator.hasPermission(getAuthentication(), (Serializable) targetId, targetType,
146+
permission);
147+
}
148+
149+
/**
150+
* Sets the {@link AuthorizationManagerFactory} to use for creating instances of
151+
* {@link AuthorizationManager}. The default is
152+
* {@link DefaultAuthorizationManagerFactory}.
153+
* @param authorizationManagerFactory the {@link AuthorizationManagerFactory} to use
154+
*/
155+
public void setAuthorizationManagerFactory(AuthorizationManagerFactory<T> authorizationManagerFactory) {
156+
Assert.notNull(authorizationManagerFactory, "authorizationManagerFactory cannot be null");
157+
this.authorizationManagerFactory = authorizationManagerFactory;
158+
}
159+
160+
/**
161+
* Sets the {@link PermissionEvaluator} to use for evaluating permission checks on
162+
* domain objects.
163+
* @param permissionEvaluator the {@link PermissionEvaluator} to use
164+
*/
165+
public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
166+
Assert.notNull(permissionEvaluator, "permissionEvaluator cannot be null");
167+
this.permissionEvaluator = permissionEvaluator;
168+
}
169+
170+
@Override
171+
public Authentication getAuthentication() {
172+
return this.authentication.get();
173+
}
174+
175+
public @Nullable Object getPrincipal() {
176+
return getAuthentication().getPrincipal();
177+
}
178+
179+
@SuppressWarnings("unchecked")
180+
private static <T> AuthorizationManagerFactory<T> defaultAuthorizationManagerFactory() {
181+
return (AuthorizationManagerFactory<T>) DEFAULT_AUTHORIZATION_MANAGER_FACTORY;
182+
}
183+
184+
}

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

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
* @author Luke Taylor
6060
* @author Evgeniy Cheban
6161
* @author Blagoja Stamatovski
62+
* @author Steve Riesenberg
6263
* @since 3.0
6364
*/
6465
public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpressionHandler<MethodInvocation>
@@ -243,27 +244,39 @@ public void setAuthorizationManagerFactory(
243244
* {@link AuthenticationTrustResolverImpl}.
244245
* @param trustResolver the {@link AuthenticationTrustResolver} to use. Cannot be
245246
* null.
247+
* @deprecated use {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
246248
*/
249+
@Deprecated(since = "7.0")
247250
public void setTrustResolver(AuthenticationTrustResolver trustResolver) {
248251
Assert.notNull(trustResolver, "trustResolver cannot be null");
249252
this.defaultAuthorizationManagerFactory.setTrustResolver(trustResolver);
250253
}
251254

252255
/**
253256
* @return The current {@link AuthenticationTrustResolver}
257+
* @deprecated use {@link DefaultAuthorizationManagerFactory#getTrustResolver()} instead
254258
*/
259+
@Deprecated(since = "7.0")
255260
protected AuthenticationTrustResolver getTrustResolver() {
256261
return this.defaultAuthorizationManagerFactory.getTrustResolver();
257262
}
258263

264+
/**
265+
* @deprecated use {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
266+
*/
259267
@Override
268+
@Deprecated(since = "7.0")
260269
public void setRoleHierarchy(@Nullable RoleHierarchy roleHierarchy) {
261270
if (roleHierarchy != null) {
262271
this.defaultAuthorizationManagerFactory.setRoleHierarchy(roleHierarchy);
263272
}
264273
}
265274

275+
/**
276+
* @deprecated use {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
277+
*/
266278
@Override
279+
@Deprecated(since = "7.0")
267280
protected @Nullable RoleHierarchy getRoleHierarchy() {
268281
return this.defaultAuthorizationManagerFactory.getRoleHierarchy();
269282
}
@@ -312,14 +325,18 @@ public void setReturnObject(@Nullable Object returnObject, EvaluationContext ctx
312325
* If null or empty, then no default role prefix is used.
313326
* </p>
314327
* @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
328+
* @deprecated use {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
315329
*/
330+
@Deprecated(since = "7.0")
316331
public void setDefaultRolePrefix(String defaultRolePrefix) {
317332
this.defaultAuthorizationManagerFactory.setRolePrefix(defaultRolePrefix);
318333
}
319334

320335
/**
321336
* @return The default role prefix
337+
* @deprecated use {@link DefaultAuthorizationManagerFactory#getRolePrefix()} instead
322338
*/
339+
@Deprecated(since = "7.0")
323340
protected String getDefaultRolePrefix() {
324341
return this.defaultAuthorizationManagerFactory.getRolePrefix();
325342
}

0 commit comments

Comments
 (0)