1818
1919import java .util .List ;
2020import java .util .function .Function ;
21- import java .util .function .Supplier ;
2221
2322import jakarta .servlet .http .HttpServletRequest ;
2423
2726import org .springframework .core .ResolvableType ;
2827import org .springframework .security .access .hierarchicalroles .NullRoleHierarchy ;
2928import org .springframework .security .access .hierarchicalroles .RoleHierarchy ;
30- import org .springframework .security .authorization .AuthenticatedAuthorizationManager ;
31- import org .springframework .security .authorization .AuthorityAuthorizationManager ;
3229import org .springframework .security .authorization .AuthorizationDecision ;
3330import org .springframework .security .authorization .AuthorizationEventPublisher ;
3431import org .springframework .security .authorization .AuthorizationManager ;
32+ import org .springframework .security .authorization .AuthorizationManagerFactory ;
3533import org .springframework .security .authorization .AuthorizationManagers ;
36- import org .springframework .security .authorization .SingleResultAuthorizationManager ;
34+ import org .springframework .security .authorization .DefaultAuthorizationManagerFactory ;
3735import org .springframework .security .authorization .SpringAuthorizationEventPublisher ;
3836import org .springframework .security .config .ObjectPostProcessor ;
3937import org .springframework .security .config .annotation .web .AbstractRequestMatcherRegistry ;
4644import org .springframework .security .web .util .matcher .RequestMatcher ;
4745import org .springframework .security .web .util .matcher .RequestMatcherEntry ;
4846import org .springframework .util .Assert ;
49- import org .springframework .util .function .SingletonSupplier ;
5047
5148/**
5249 * Adds a URL based authorization using {@link AuthorizationManager}.
5350 *
5451 * @param <H> the type of {@link HttpSecurityBuilder} that is being configured.
5552 * @author Evgeniy Cheban
53+ * @author Steve Riesenberg
5654 * @since 5.5
5755 */
5856public final class AuthorizeHttpRequestsConfigurer <H extends HttpSecurityBuilder <H >>
@@ -62,9 +60,7 @@ public final class AuthorizeHttpRequestsConfigurer<H extends HttpSecurityBuilder
6260
6361 private final AuthorizationEventPublisher publisher ;
6462
65- private final Supplier <RoleHierarchy > roleHierarchy ;
66-
67- private String rolePrefix = "ROLE_" ;
63+ private final AuthorizationManagerFactory <RequestAuthorizationContext > authorizationManagerFactory ;
6864
6965 private ObjectPostProcessor <AuthorizationManager <HttpServletRequest >> postProcessor = ObjectPostProcessor
7066 .identity ();
@@ -81,20 +77,43 @@ public AuthorizeHttpRequestsConfigurer(ApplicationContext context) {
8177 else {
8278 this .publisher = new SpringAuthorizationEventPublisher (context );
8379 }
84- this .roleHierarchy = SingletonSupplier .of (() -> (context .getBeanNamesForType (RoleHierarchy .class ).length > 0 )
85- ? context .getBean (RoleHierarchy .class ) : new NullRoleHierarchy ());
86- String [] grantedAuthorityDefaultsBeanNames = context .getBeanNamesForType (GrantedAuthorityDefaults .class );
87- if (grantedAuthorityDefaultsBeanNames .length > 0 ) {
88- GrantedAuthorityDefaults grantedAuthorityDefaults = context .getBean (GrantedAuthorityDefaults .class );
89- this .rolePrefix = grantedAuthorityDefaults .getRolePrefix ();
90- }
80+ this .authorizationManagerFactory = getAuthorizationManagerFactory (context );
9181 ResolvableType type = ResolvableType .forClassWithGenerics (ObjectPostProcessor .class ,
9282 ResolvableType .forClassWithGenerics (AuthorizationManager .class , HttpServletRequest .class ));
9383 ObjectProvider <ObjectPostProcessor <AuthorizationManager <HttpServletRequest >>> provider = context
9484 .getBeanProvider (type );
9585 provider .ifUnique ((postProcessor ) -> this .postProcessor = postProcessor );
9686 }
9787
88+ private AuthorizationManagerFactory <RequestAuthorizationContext > getAuthorizationManagerFactory (
89+ ApplicationContext context ) {
90+ ResolvableType authorizationManagerFactoryType = ResolvableType
91+ .forClassWithGenerics (AuthorizationManagerFactory .class , RequestAuthorizationContext .class );
92+
93+ // Handle fallback to generic type
94+ if (context .getBeanNamesForType (authorizationManagerFactoryType ).length == 0 ) {
95+ authorizationManagerFactoryType = ResolvableType .forClassWithGenerics (AuthorizationManagerFactory .class ,
96+ Object .class );
97+ }
98+
99+ ObjectProvider <AuthorizationManagerFactory <RequestAuthorizationContext >> authorizationManagerFactoryProvider = context
100+ .getBeanProvider (authorizationManagerFactoryType );
101+
102+ return authorizationManagerFactoryProvider .getIfAvailable (() -> {
103+ RoleHierarchy roleHierarchy = context .getBeanProvider (RoleHierarchy .class )
104+ .getIfAvailable (NullRoleHierarchy ::new );
105+ GrantedAuthorityDefaults grantedAuthorityDefaults = context .getBeanProvider (GrantedAuthorityDefaults .class )
106+ .getIfAvailable ();
107+ String rolePrefix = (grantedAuthorityDefaults != null ) ? grantedAuthorityDefaults .getRolePrefix () : "ROLE_" ;
108+
109+ DefaultAuthorizationManagerFactory <RequestAuthorizationContext > authorizationManagerFactory = new DefaultAuthorizationManagerFactory <>();
110+ authorizationManagerFactory .setRoleHierarchy (roleHierarchy );
111+ authorizationManagerFactory .setRolePrefix (rolePrefix );
112+
113+ return authorizationManagerFactory ;
114+ });
115+ }
116+
98117 /**
99118 * The {@link AuthorizationManagerRequestMatcherRegistry} is what users will interact
100119 * with after applying the {@link AuthorizeHttpRequestsConfigurer}.
@@ -173,7 +192,7 @@ private AuthorizationManager<HttpServletRequest> createAuthorizationManager() {
173192 @ Override
174193 protected AuthorizedUrl chainRequestMatchers (List <RequestMatcher > requestMatchers ) {
175194 this .unmappedMatchers = requestMatchers ;
176- return new AuthorizedUrl (requestMatchers );
195+ return new AuthorizedUrl (requestMatchers , AuthorizeHttpRequestsConfigurer . this . authorizationManagerFactory );
177196 }
178197
179198 /**
@@ -201,20 +220,31 @@ public class AuthorizedUrl {
201220
202221 private final List <? extends RequestMatcher > matchers ;
203222
223+ private AuthorizationManagerFactory <RequestAuthorizationContext > authorizationManagerFactory ;
224+
204225 private boolean not ;
205226
206227 /**
207228 * Creates an instance.
208229 * @param matchers the {@link RequestMatcher} instances to map
230+ * @param authorizationManagerFactory the {@link AuthorizationManagerFactory} for
231+ * creating instances of {@link AuthorizationManager}
209232 */
210- AuthorizedUrl (List <? extends RequestMatcher > matchers ) {
233+ AuthorizedUrl (List <? extends RequestMatcher > matchers ,
234+ AuthorizationManagerFactory <RequestAuthorizationContext > authorizationManagerFactory ) {
211235 this .matchers = matchers ;
236+ this .authorizationManagerFactory = authorizationManagerFactory ;
212237 }
213238
214239 protected List <? extends RequestMatcher > getMatchers () {
215240 return this .matchers ;
216241 }
217242
243+ void setAuthorizationManagerFactory (
244+ AuthorizationManagerFactory <RequestAuthorizationContext > authorizationManagerFactory ) {
245+ this .authorizationManagerFactory = authorizationManagerFactory ;
246+ }
247+
218248 /**
219249 * Negates the following authorization rule.
220250 * @return the {@link AuthorizedUrl} for further customization
@@ -231,7 +261,7 @@ public AuthorizedUrl not() {
231261 * customizations
232262 */
233263 public AuthorizationManagerRequestMatcherRegistry permitAll () {
234- return access (SingleResultAuthorizationManager .permitAll ());
264+ return access (this . authorizationManagerFactory .permitAll ());
235265 }
236266
237267 /**
@@ -240,7 +270,7 @@ public AuthorizationManagerRequestMatcherRegistry permitAll() {
240270 * customizations
241271 */
242272 public AuthorizationManagerRequestMatcherRegistry denyAll () {
243- return access (SingleResultAuthorizationManager .denyAll ());
273+ return access (this . authorizationManagerFactory .denyAll ());
244274 }
245275
246276 /**
@@ -251,8 +281,7 @@ public AuthorizationManagerRequestMatcherRegistry denyAll() {
251281 * customizations
252282 */
253283 public AuthorizationManagerRequestMatcherRegistry hasRole (String role ) {
254- return access (withRoleHierarchy (AuthorityAuthorizationManager
255- .hasAnyRole (AuthorizeHttpRequestsConfigurer .this .rolePrefix , new String [] { role })));
284+ return access (this .authorizationManagerFactory .hasRole (role ));
256285 }
257286
258287 /**
@@ -264,8 +293,7 @@ public AuthorizationManagerRequestMatcherRegistry hasRole(String role) {
264293 * customizations
265294 */
266295 public AuthorizationManagerRequestMatcherRegistry hasAnyRole (String ... roles ) {
267- return access (withRoleHierarchy (
268- AuthorityAuthorizationManager .hasAnyRole (AuthorizeHttpRequestsConfigurer .this .rolePrefix , roles )));
296+ return access (this .authorizationManagerFactory .hasAnyRole (roles ));
269297 }
270298
271299 /**
@@ -275,7 +303,7 @@ public AuthorizationManagerRequestMatcherRegistry hasAnyRole(String... roles) {
275303 * customizations
276304 */
277305 public AuthorizationManagerRequestMatcherRegistry hasAuthority (String authority ) {
278- return access (withRoleHierarchy ( AuthorityAuthorizationManager . hasAuthority (authority ) ));
306+ return access (this . authorizationManagerFactory . hasAuthority (authority ));
279307 }
280308
281309 /**
@@ -286,13 +314,7 @@ public AuthorizationManagerRequestMatcherRegistry hasAuthority(String authority)
286314 * customizations
287315 */
288316 public AuthorizationManagerRequestMatcherRegistry hasAnyAuthority (String ... authorities ) {
289- return access (withRoleHierarchy (AuthorityAuthorizationManager .hasAnyAuthority (authorities )));
290- }
291-
292- private AuthorityAuthorizationManager <RequestAuthorizationContext > withRoleHierarchy (
293- AuthorityAuthorizationManager <RequestAuthorizationContext > manager ) {
294- manager .setRoleHierarchy (AuthorizeHttpRequestsConfigurer .this .roleHierarchy .get ());
295- return manager ;
317+ return access (this .authorizationManagerFactory .hasAnyAuthority (authorities ));
296318 }
297319
298320 /**
@@ -301,7 +323,7 @@ private AuthorityAuthorizationManager<RequestAuthorizationContext> withRoleHiera
301323 * customizations
302324 */
303325 public AuthorizationManagerRequestMatcherRegistry authenticated () {
304- return access (AuthenticatedAuthorizationManager .authenticated ());
326+ return access (this . authorizationManagerFactory .authenticated ());
305327 }
306328
307329 /**
@@ -313,7 +335,7 @@ public AuthorizationManagerRequestMatcherRegistry authenticated() {
313335 * @see RememberMeConfigurer
314336 */
315337 public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated () {
316- return access (AuthenticatedAuthorizationManager .fullyAuthenticated ());
338+ return access (this . authorizationManagerFactory .fullyAuthenticated ());
317339 }
318340
319341 /**
@@ -324,7 +346,7 @@ public AuthorizationManagerRequestMatcherRegistry fullyAuthenticated() {
324346 * @see RememberMeConfigurer
325347 */
326348 public AuthorizationManagerRequestMatcherRegistry rememberMe () {
327- return access (AuthenticatedAuthorizationManager .rememberMe ());
349+ return access (this . authorizationManagerFactory .rememberMe ());
328350 }
329351
330352 /**
@@ -334,7 +356,7 @@ public AuthorizationManagerRequestMatcherRegistry rememberMe() {
334356 * @since 5.8
335357 */
336358 public AuthorizationManagerRequestMatcherRegistry anonymous () {
337- return access (AuthenticatedAuthorizationManager .anonymous ());
359+ return access (this . authorizationManagerFactory .anonymous ());
338360 }
339361
340362 /**
0 commit comments