11/*
2- * Copyright 2002-2023 the original author or authors.
2+ * Copyright 2002-2025 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.
1717package org .springframework .security .access .expression ;
1818
1919import java .io .Serializable ;
20- import java .util .Collection ;
21- import java .util .Set ;
2220import java .util .function .Supplier ;
2321
2422import org .jspecify .annotations .Nullable ;
2523
2624import org .springframework .security .access .PermissionEvaluator ;
2725import org .springframework .security .access .hierarchicalroles .RoleHierarchy ;
2826import org .springframework .security .authentication .AuthenticationTrustResolver ;
29- import org .springframework .security .authentication .AuthenticationTrustResolverImpl ;
27+ import org .springframework .security .authorization .AuthorizationManager ;
28+ import org .springframework .security .authorization .AuthorizationManagerFactory ;
29+ import org .springframework .security .authorization .AuthorizationResult ;
30+ import org .springframework .security .authorization .DefaultAuthorizationManagerFactory ;
3031import org .springframework .security .core .Authentication ;
31- import org .springframework .security .core .GrantedAuthority ;
32- import org .springframework .security .core .authority .AuthorityUtils ;
3332import org .springframework .util .Assert ;
3433import org .springframework .util .function .SingletonSupplier ;
3534
4241 */
4342public abstract class SecurityExpressionRoot implements SecurityExpressionOperations {
4443
45- private final Supplier <Authentication > authentication ;
44+ private static final AuthorizationManagerFactory <Object > DEFAULT_AUTHORIZATION_MANAGER_FACTORY = new DefaultAuthorizationManagerFactory <>();
45+
46+ private static final Object DEFAULT_OBJECT = new Object ();
4647
47- private AuthenticationTrustResolver trustResolver = new AuthenticationTrustResolverImpl () ;
48+ private final Supplier < Authentication > authentication ;
4849
49- private @ Nullable RoleHierarchy roleHierarchy ;
50+ private final Object object ;
5051
51- private @ Nullable Set < String > roles ;
52+ private @ Nullable DefaultAuthorizationManagerFactory < Object > defaultAuthorizationManagerFactory ;
5253
53- private String defaultRolePrefix = "ROLE_" ;
54+ private AuthorizationManagerFactory < Object > authorizationManagerFactory = DEFAULT_AUTHORIZATION_MANAGER_FACTORY ;
5455
5556 /**
5657 * Allows "permitAll" expression
@@ -77,9 +78,11 @@ public abstract class SecurityExpressionRoot implements SecurityExpressionOperat
7778 /**
7879 * Creates a new instance
7980 * @param authentication the {@link Authentication} to use. Cannot be null.
81+ * @deprecated use {@link #SecurityExpressionRoot(Supplier, Object)} instead
8082 */
83+ @ Deprecated (since = "7.0" )
8184 public SecurityExpressionRoot (Authentication authentication ) {
82- this (() -> authentication );
85+ this (() -> authentication , DEFAULT_OBJECT );
8386 }
8487
8588 /**
@@ -88,44 +91,48 @@ public SecurityExpressionRoot(Authentication authentication) {
8891 * @param authentication the {@link Supplier} of the {@link Authentication} to use.
8992 * Cannot be null.
9093 * @since 5.8
94+ * @deprecated use {@link #SecurityExpressionRoot(Supplier, Object)} instead
9195 */
96+ @ Deprecated (since = "7.0" )
9297 public SecurityExpressionRoot (Supplier <Authentication > authentication ) {
98+ this (authentication , DEFAULT_OBJECT );
99+ }
100+
101+ /**
102+ * Creates a new instance that uses lazy initialization of the {@link Authentication}
103+ * object.
104+ * @param authentication the {@link Supplier} of the {@link Authentication} to use.
105+ * Cannot be null.
106+ * @param object the object being authorized
107+ * @since 7.0
108+ */
109+ public SecurityExpressionRoot (Supplier <Authentication > authentication , Object object ) {
93110 this .authentication = SingletonSupplier .of (() -> {
94111 Authentication value = authentication .get ();
95112 Assert .notNull (value , "Authentication object cannot be null" );
96113 return value ;
97114 });
115+ this .object = object ;
98116 }
99117
100118 @ Override
101119 public final boolean hasAuthority (String authority ) {
102- return hasAnyAuthority (authority );
120+ return isGranted ( this . authorizationManagerFactory . hasAnyAuthority (authority ) );
103121 }
104122
105123 @ Override
106124 public final boolean hasAnyAuthority (String ... authorities ) {
107- return hasAnyAuthorityName ( null , authorities );
125+ return isGranted ( this . authorizationManagerFactory . hasAnyAuthority ( authorities ) );
108126 }
109127
110128 @ Override
111129 public final boolean hasRole (String role ) {
112- return hasAnyRole ( role );
130+ return isGranted ( this . authorizationManagerFactory . hasRole ( role ) );
113131 }
114132
115133 @ Override
116134 public final boolean hasAnyRole (String ... roles ) {
117- return hasAnyAuthorityName (this .defaultRolePrefix , roles );
118- }
119-
120- private boolean hasAnyAuthorityName (@ Nullable String prefix , String ... roles ) {
121- Set <String > roleSet = getAuthoritySet ();
122- for (String role : roles ) {
123- String defaultedRole = getRoleWithDefaultPrefix (prefix , role );
124- if (roleSet .contains (defaultedRole )) {
125- return true ;
126- }
127- }
128- return false ;
135+ return isGranted (this .authorizationManagerFactory .hasAnyRole (roles ));
129136 }
130137
131138 @ Override
@@ -135,33 +142,37 @@ public final Authentication getAuthentication() {
135142
136143 @ Override
137144 public final boolean permitAll () {
138- return true ;
145+ return isGranted ( this . authorizationManagerFactory . permitAll ()) ;
139146 }
140147
141148 @ Override
142149 public final boolean denyAll () {
143- return false ;
150+ return isGranted ( this . authorizationManagerFactory . denyAll ()) ;
144151 }
145152
146153 @ Override
147154 public final boolean isAnonymous () {
148- return this .trustResolver . isAnonymous ( getAuthentication ());
155+ return isGranted ( this .authorizationManagerFactory . anonymous ());
149156 }
150157
151158 @ Override
152159 public final boolean isAuthenticated () {
153- return this .trustResolver . isAuthenticated ( getAuthentication ());
160+ return isGranted ( this .authorizationManagerFactory . authenticated ());
154161 }
155162
156163 @ Override
157164 public final boolean isRememberMe () {
158- return this .trustResolver . isRememberMe ( getAuthentication ());
165+ return isGranted ( this .authorizationManagerFactory . rememberMe ());
159166 }
160167
161168 @ Override
162169 public final boolean isFullyAuthenticated () {
163- Authentication authentication = getAuthentication ();
164- return this .trustResolver .isFullyAuthenticated (authentication );
170+ return isGranted (this .authorizationManagerFactory .fullyAuthenticated ());
171+ }
172+
173+ private boolean isGranted (AuthorizationManager <Object > authorizationManager ) {
174+ AuthorizationResult authorizationResult = authorizationManager .authorize (this .authentication , this .object );
175+ return (authorizationResult != null && authorizationResult .isGranted ());
165176 }
166177
167178 /**
@@ -173,12 +184,22 @@ public final boolean isFullyAuthenticated() {
173184 return getAuthentication ().getPrincipal ();
174185 }
175186
187+ /**
188+ * @deprecated Use
189+ * {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
190+ */
191+ @ Deprecated (since = "7.0" )
176192 public void setTrustResolver (AuthenticationTrustResolver trustResolver ) {
177- this . trustResolver = trustResolver ;
193+ getDefaultAuthorizationManagerFactory (). setTrustResolver ( trustResolver ) ;
178194 }
179195
196+ /**
197+ * @deprecated Use
198+ * {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
199+ */
200+ @ Deprecated (since = "7.0" )
180201 public void setRoleHierarchy (RoleHierarchy roleHierarchy ) {
181- this . roleHierarchy = roleHierarchy ;
202+ getDefaultAuthorizationManagerFactory (). setRoleHierarchy ( roleHierarchy ) ;
182203 }
183204
184205 /**
@@ -193,20 +214,32 @@ public void setRoleHierarchy(RoleHierarchy roleHierarchy) {
193214 * If null or empty, then no default role prefix is used.
194215 * </p>
195216 * @param defaultRolePrefix the default prefix to add to roles. Default "ROLE_".
217+ * @deprecated Use
218+ * {@link #setAuthorizationManagerFactory(AuthorizationManagerFactory)} instead
196219 */
220+ @ Deprecated (since = "7.0" )
197221 public void setDefaultRolePrefix (String defaultRolePrefix ) {
198- this .defaultRolePrefix = defaultRolePrefix ;
222+ getDefaultAuthorizationManagerFactory ().setRolePrefix (defaultRolePrefix );
223+ }
224+
225+ /**
226+ * Sets the {@link AuthorizationManagerFactory} to use for creating instances of
227+ * {@link AuthorizationManager}.
228+ * @param authorizationManagerFactory the {@link AuthorizationManagerFactory} to use
229+ * @since 7.0
230+ */
231+ public void setAuthorizationManagerFactory (AuthorizationManagerFactory <Object > authorizationManagerFactory ) {
232+ Assert .notNull (authorizationManagerFactory , "authorizationManagerFactory cannot be null" );
233+ this .authorizationManagerFactory = authorizationManagerFactory ;
199234 }
200235
201- private Set <String > getAuthoritySet () {
202- if (this .roles == null ) {
203- Collection <? extends GrantedAuthority > userAuthorities = getAuthentication ().getAuthorities ();
204- if (this .roleHierarchy != null ) {
205- userAuthorities = this .roleHierarchy .getReachableGrantedAuthorities (userAuthorities );
206- }
207- this .roles = AuthorityUtils .authorityListToSet (userAuthorities );
236+ private DefaultAuthorizationManagerFactory <Object > getDefaultAuthorizationManagerFactory () {
237+ if (this .defaultAuthorizationManagerFactory == null ) {
238+ this .defaultAuthorizationManagerFactory = new DefaultAuthorizationManagerFactory <>();
239+ this .authorizationManagerFactory = this .defaultAuthorizationManagerFactory ;
208240 }
209- return this .roles ;
241+
242+ return this .defaultAuthorizationManagerFactory ;
210243 }
211244
212245 @ Override
@@ -225,24 +258,4 @@ public void setPermissionEvaluator(PermissionEvaluator permissionEvaluator) {
225258 this .permissionEvaluator = permissionEvaluator ;
226259 }
227260
228- /**
229- * Prefixes role with defaultRolePrefix if defaultRolePrefix is non-null and if role
230- * does not already start with defaultRolePrefix.
231- * @param defaultRolePrefix
232- * @param role
233- * @return
234- */
235- private static String getRoleWithDefaultPrefix (@ Nullable String defaultRolePrefix , String role ) {
236- if (role == null ) {
237- return role ;
238- }
239- if (defaultRolePrefix == null || defaultRolePrefix .length () == 0 ) {
240- return role ;
241- }
242- if (role .startsWith (defaultRolePrefix )) {
243- return role ;
244- }
245- return defaultRolePrefix + role ;
246- }
247-
248261}
0 commit comments