authorizeHttpRequests
does not support expression-based rules in its DSL. While it is recommended to migrate expressions to concrete authorization manager implementations, applications can use WebExpressionAuthorizationManager
as a migration step.
Given that authorizeRequests
is due to be deprecated in #15174, it would be nice to make this simpler, if possible. One place of friction is configuring the expression handler to support bean references. To do this, the expression handler must be provided after construction is complete. Aside from causing the parsed expression to be re-parsed after construction, it also makes it cumbersome when there are multiple expressions to replace.
This ticket adds a builder so that applications can do:
@Bean
WebExpressionAuthorizationManager.Builder authz() {
return WebExpressionAuthorizationManager.withDefaults();
}
This allows migrating from something like the following:
@Bean
SecurityFilterChain httpSecurity(HttpSecurity http) throws Exception {
http
.authorizeRequests((authorize) -> authorize
.mvcMatchers(GET, "/api/**").access("@bean.hasPermission('api:read') || hasRole('ADMIN')")
.mvcMatchers("/api/**").access("@bean.hasPermission('api:write') || hasRole('ADMIN')")
)
return http.build();
}
To this:
@Bean
WebExpressionAuthorizationManager.Builder authz() {
return WebExpressionAuthorizationManager.withDefaults();
}
@Bean
SecurityFilterChain httpSecurity(HttpSecurity http, WebExpressionAuthorizationManager.Builder authz) throws Exception {
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(GET, "/api/**").access(authz.expression("@bean.hasPermission('api:read') || hasRole('ADMIN')"))
.requestMatchers("/api/**").access(authz.expression("@bean.hasPermission('api:write') || hasRole('ADMIN')"))
)
return http.build();
}
Instead of this:
@Bean
DefaultHttpSecurityExpressionHandler expressionHandler() {
return new DefaultHttpSecurityExpressionHandler();
}
@Bean
SecurityFilterChain httpSecurity(HttpSecurity http, DefaultHttpSecurityExpressionHandler expressionHandler) throws Exception {
WebExpressionAuthorizationManager getApi = new WebExpressionAuthorizationManager("@bean.hasPermission('api:read') || hasRole('ADMIN')");
getApi.setExpressionHandler(expressionHandler);
WebExpressionAuthorizationManager api = new WebExpressionAuthorizationManager("@bean.hasPermission('api:write') || hasRole('ADMIN')");
api.setExpressionHandler(expressionHandler);
http
.authorizeHttpRequests((authorize) -> authorize
.requestMatchers(GET, "/api/**").access(getApi)
.requestMatchers("/api/**").access(api)
)
return http.build();
}
NOTE: