Describe the bug
If I use @PreAuthorize, the validation for @RequestParam does not work.
To Reproduce
//-----------------------------------------------------
// With PreAuthorize: Validation does NOT work
//-----------------------------------------------------
@GetMapping("withPreAuthorize")
@ResponseStatus(HttpStatus.OK)
@PreAuthorize("hasRole('USER')")
suspend fun withPreAuthorize(
@RequestParam(defaultValue = "100", required = true) @Min(1) @Max(100) limit: Int,
): String {
return "OK"
}
//-----------------------------------------------------
// Without PreAuthorize: Validation works
//-----------------------------------------------------
@GetMapping("withoutPreAuthorize")
@ResponseStatus(HttpStatus.OK)
suspend fun withoutPreAuthorize(
@RequestParam(defaultValue = "100", required = true) @Min(1) @Max(100) limit: Int,
): String {
return "OK"
}
Expected behavior
A clear and concise description of what you expected to happen.
@PreAuthorize should not disturb validator.
Sample https://github.com/und3rs/springboot-helpme You can test with '\src\test\kotlin\test.http'.
Comment From: marcusdacoregio
Thanks for reaching out @und3rs.
This seems to be related to https://github.com/spring-projects/spring-security/issues/10252 where the PrePostAdviceReactiveMethodInterceptor does not call the others interceptors in the chain.
Are you interested in submitting a pull request to fix the issue?
Comment From: igorpele
Hi, I just had a look at this code and there is obviously a bug in PrePostAdviceReactiveMethodInterceptor calling Kotlin suspending functions:
```
if (isSuspendingFunction) {
response = toInvoke.flatMapMany((auth) -> Flux
.from(CoroutinesUtils.invokeSuspendingFunction(invocation.getMethod(), invocation.getThis(),
invocation.getArguments()))
.map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r));
}
because the suspending function is called directly using `CoroutinesUtils.invokeSuspendingFunction` without the `proceed` method.
The obvious way to solve it would be to call the proceed method
Mono<?> response = toInvoke.flatMap((auth) -> Mono .from(PrePostAdviceReactiveMethodInterceptor.<Mono<?>>proceed(invocation)) .map((r) -> (attr != null) ? this.postAdvice.after(auth, invocation, attr, r) : r)); ```
but that would mean omitting the special treatment of Kotlin suspending function, which is imho architecturally not best placed in a MethodInterceptor and should be handled somewhere centrally ie by placing a dedicated MethodInvocation in the chain. Any thoughts?
Comment From: und3rs
Any update, please?
Comment From: jzheaux
Please see my comment in #10252. Given that, I'll mark this as closed as of 6.2.0.
I can also confirm that when I take the sample provided in the OP and update it to the latest, it demonstrates the expected behavior.
Comment From: und3rs
Thanks a lot!!! I checked this bug fixed and update my project successfuly!