BugReport Spring Boot version 3.2.0 Summary: SpEL can' t extract parameters

A controller is annotated with:

@PreAuthorize("hasPermission(#myResource,'WRITE') ")

In my class that checks the permission:

class MySecurityExpressionRoot extends SecurityExpressionRoot implements MethodSecurityExpressionOperations

The call:

@Override
public boolean hasPermission(Object target, Object permission) {
    return predicateMap.getOrDefault(target.getClass().getName(), (o, p) -> false).test(target, BasePermission.valueOf(permission.toString()));
}

fails with an NPE, because target is null. It was working with spring boot version 3.1.2 The bug is critical because I can' t release a new version due to missing right protection

Comment From: bclozel

Sorry but we can't help you. Please share the complete stack trace as well as a minimal sample application (ideally creates with start.spring.io) so we can reproduce the problem.

Comment From: DrScho

Dear Brian,

sorry, I won‘ t provide an example because of time issues. But I think I gave a detailed description of the problem. The error encounted with spring boot versions 3.2.0 and 3.2.1. It is working with spring boot version 3.1.2. As described in: https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html#repeated-annotations

Point 3 is not working any more, because parsing of the expression failed, so that the evaluation context is null. There must have been a change in Spring SpEL between the spring versions The expression that can’ t be parsed is:

@PreAuthorize("hasPermission(#myResource,'write') ")
public ResponseEntity<Long> saveMyEntity(@Valid @RequestBody MyResource myResource, UriComponentsBuilder b) {

This should be correct compared with https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

@PreAuthorize("hasPermission(#contact, 'admin')")
  public void deletePermission(Contact contact, Sid recipient, Permission permission);

It seems to be only a problem with hasPermission, hasRole might work Thilo

Comment From: DrScho

Dear Brian,

sorry, I won‘ t provide an example because of time issues. But I think I gave a detailed description of the problem. The error encounted with spring boot versions 3.2.0 and 3.2.1. It is working with spring boot version 3.1.2. As described in: https://docs.spring.io/spring-security/reference/servlet/authorization/method-security.html#repeated-annotations

Point 3 is not working any more, because parsing of the expression failed, so that the evaluation context is null. There must have been a change in Spring SpEL between the spring versions The expression that can’ t be parsed is: @PreAuthorize("hasPermission(#myResource,'write') ") public ResponseEntity @.*** @RequestBody MyResource myResource, UriComponentsBuilder b) {

This should be correct compared with https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html @PreAuthorize("hasPermission(#contact, 'admin')") public void deletePermission(Contact contact, Sid recipient, Permission permission);

It seems to be only a problem with hasPermission, hasRole might work Thilo

Beste Grüße

Dr. Thilo Schottelius, Industrial Lines Digital Lab, HDI IT | HDI AG, HDI-Platz 1, 30659 Hannover | Telefon +49 (511) 645-4867, Fax (0511) 645-4545, E-Mail @.*** | www.hdi.de

Informationen gem. § 80 Aktiengesetz: HDI AG, HDI-Platz 1, 30659 Hannover; Vorsitzender des Aufsichtsrats: Torsten Leue; Vorstand: Caroline Schlienkamp (Sprecherin), Stefan Eversberg, Michael Heinen, Dr. Christian Hermelingmeier, Jens Köwing; HR Hannover B 60722, Sitz Hannover

Von: Brian Clozel @.> Gesendet: Donnerstag, 21. Dezember 2023 09:22 An: spring-projects/spring-boot @.> Cc: Schottelius, Thilo @.>; Author @.> Betreff: Re: [spring-projects/spring-boot] SpEL containing argument references not working in Spring Boot 3.2.0 (Issue #38895)

Sorry but we can't help you. Please share the complete stack trace as well as a minimal sample application (ideally creates with start.spring.io) so we can reproduce the problem.

— Reply to this email directly, view it on GitHubhttps://github.com/spring-projects/spring-boot/issues/38895#issuecomment-1865845908, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMKN3THQIWL4TH4CNGJUW2DYKPWRHAVCNFSM6AAAAABA57D6MCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQNRVHA2DKOJQHA. You are receiving this because you authored the thread.Message ID: @.**@.**>>

Comment From: philwebb

I won‘ t provide an example because of time issues

Unfortunately it's really hard and time consuming for us to try and reproduce an problem like this from fragments of code in the issue tracker. I'm going to close this one until you have the time needed to help us diagnose the problem.

Comment From: vom3st

Can confirm, this is an issue and prevents us from upgrading to Spring 3.2.1. Was working in 3.1.2.

Comment From: bclozel

@vom3st we're still waiting on a minimal sample that reproduces the problem. If you have time to work on one, we'd be happy to reopen this issue.

Comment From: vom3st

Thank you @bclozel, I try to provide an example. Should have said that earlier (-:

Comment From: bclozel

We did https://github.com/spring-projects/spring-boot/issues/38895#issuecomment-1865845908

Comment From: vom3st

Yes, you did, I meant I should have clarified that earlier, that I will provide an example, as you already said you need an example. Sorry :)

Comment From: vom3st

I tried to create a minimal example and in the minimal example it is working. Yay.

But I noticed something: The standard StandardReflectionParameterNameDiscoverer is using method.getParameters().

This translates to (simplified): MyWebController.class.getMethods()[0].getParameters()

In my (broken) version, the parameter names are arg0, arg1, etc, while in the working (example) project it is myParameter1, myParameter2, so having the actual parameter names. This means it cannot find the names, because the reflection names are not matching the source names. Which is very weird. Because if I try to get the parameter names, let's say of StandardReflectionParameterNameDiscoverer they match.

As it is working in 3.1.2 something is interfering with my code when moving to 3.2.1. Any ideas on what this might be or how to debug this further?

Comment From: wilkinsona

Your code needs to be compiled with -parameters and it looks like that's not happening with Spring Boot 3.2.1. It's impossible to say why that's the case without knowing more about how you're building and running your app.

Comment From: DrScho

Good morning,

we analysed the probblem. Yes, you have to add the -paramters to VM options, otherwise parameters have not being compiled into byte code. But there is an additional issue that fixed parameter names like #a0 (first param), #a1 are expected. Before you could refer to the real parameter name in the method signature like #id

Beste Grüße

Dr. Thilo Schottelius, Industrial Lines Digital Lab, HDI IT | HDI AG, HDI-Platz 1, 30659 Hannover | Telefon +49 (511) 645-4867, Fax (0511) 645-4545, E-Mail @.*** | www.hdi.de

Informationen gem. § 80 Aktiengesetz: HDI AG, HDI-Platz 1, 30659 Hannover; Vorsitzender des Aufsichtsrats: Torsten Leue; Vorstand: Caroline Schlienkamp (Sprecherin), Stefan Eversberg, Michael Heinen, Dr. Christian Hermelingmeier, Jens Köwing; HR Hannover B 60722, Sitz Hannover

Von: Andy Wilkinson @.> Gesendet: Mittwoch, 10. Januar 2024 19:46 An: spring-projects/spring-boot @.> Cc: Schottelius, Thilo @.>; Author @.> Betreff: Re: [spring-projects/spring-boot] SpEL containing argument references not working in Spring Boot 3.2.0 (Issue #38895)

Your code needs to be compiled with -parameters and it looks like that's not happening with Spring Boot 3.2.1. It's impossible to say why that's the case without knowing more about how you're building and running your app,

— Reply to this email directly, view it on GitHubhttps://github.com/spring-projects/spring-boot/issues/38895#issuecomment-1885424587, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AMKN3TECOUSKNVTR6HF33R3YN3OWPAVCNFSM6AAAAABA57D6MCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQOBVGQZDINJYG4. You are receiving this because you authored the thread.Message ID: @.**@.**>>

Comment From: vom3st

Thanks for the tip with the -parameters, I did not know about it. Just learned something. Yay.

This was however not the root cause of the problem. I was not able to reproduce the issue in a demo environment, which was very odd, so I finally compiled the whole thing and started the jar from command line et voila it worked. No issues.

I did that in various java and gradle combinations and no issues at all. As soon as I started it in debug mode (from the IDE) it didn't work.

Eventually I wiped the whole workspace and started from scratch and then it also worked.

TL;DR: Somehow IntelliJ messed up my local workspace when switching between versions, although I cleaned out everything and invalided the caches. Only hard deleting all intellij files manually and starting the workspace from scratch worked. Damn you IntelliJ.

Sorry for any inconvenience this may caused. If you are at FOSDEM this year, I will buy you a ~bear~ beer, just ping me ahead of time, so we can exchange contact information

Cheers.