I had to migrate my spring boot application from spring boot 2
to spring boot 3
. Along with that change I had to migrate from javax
to jakarta
. One main change was migrating security functionality from WebSecurityConfigurerAdapter
to SecurityFilterChain
. During this migration process, I faced several difficulties and among those difficulties, I still couldn’t solve one case related to SpEL
.
The way it was handled in spring boot 2
:
(The access
API expects a String argument)
private ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry mvcMatchers(
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry) {
final List<SecurityProperties.RequestMatcher> securedUrls = securityProperties.getSecured();
securedUrls.forEach(entry -> {
if (entry.getMethods() != null && !entry.getMethods().isEmpty()) {
entry.getMethods().stream().forEach(httpMethod -> {
ExpressionUrlAuthorizationConfigurer.AuthorizedUrl authorizedUrl = registry
.mvcMatchers(httpMethod, entry.getPatterns().toArray(new String[]{}));
authorizedUrl.fullyAuthenticated();
Optional.ofNullable(entry.getAccess()).ifPresent(spEL -> authorizedUrl.access(spEL));
});
}
});
return registry;
}
The access
API has been changed with spring boot 3. Now it requires AuthorizationManager<RequestAuthorizationContext> manager
argument. I did attempt to convert my String SpEL
expression into required argument type and continue yet it didn’t work as expected.
My spring boot 3
attempt to solve the issue:
private void configureRequests(AuthorizeHttpRequestsConfigurer<HttpSecurity>.AuthorizationManagerRequestMatcherRegistry requests) {
final List<SecurityProperties.RequestMatcher> securedUrls = securityProperties.getSecured();
if (securedUrls != null) {
securedUrls.forEach(entry -> {
if (entry.getMethods() != null && !entry.getMethods().isEmpty()) {
entry.getMethods().forEach(httpMethod -> {
var authorizedUrl = requests.requestMatchers(httpMethod, entry.getPatterns().toArray(new String[]{}));
authorizedUrl.fullyAuthenticated();
Optional.ofNullable(entry.getAccess()).ifPresent(spEL -> {
var manager = new WebExpressionAuthorizationManager(spEL);
authorizedUrl.access(manager);
});
});
}
});
}
requests.anyRequest().permitAll();
}
With spring boot 2
it was very easy to provide the String SpEL
expression and it did handle itself very well. Below is one example of such:
hasAuthority('role1') || hasAuthority('role2') || hasAuthority('role3') || request.getHeader('header_name') == 'header_value')
I am missing this easy configuration with spring boot 3
and I had to find a workaround solution. My solution was to manually go through the SpEL
expression configuration and enable security as shown below:
requests.requestMatchers(httpMethod, entry.getPatterns().toArray(new String[]{}))
.hasAuthority(authority);
This is lot of work and very hard to tackle complex SpEL
expressions. My concern is if it was so easy to provide the SpEL
expression in spring boot 2
, it can’t be that difficult to do the same in spring boot 3
. I think I am missing something and really appreciate if anyone could help me to solve this. Thank you!
You need to sign in to view this answers
Leave feedback about this