You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot Webflux @PreAuthorize的SpEL传参始终为null问题求助

问题:Webflux Security自定义@PreAuthorize校验时,路径参数传递为null

我在Spring Boot 3.2.2结合Webflux Security的项目中,尝试通过ReactiveMethodSecurity自定义@PreAuthorize权限校验,用于检查用户对"space"的访问权限。自定义校验类代码如下:

@Component(value = "SpaceAccess")
@RequiredArgsConstructor
@Slf4j
public class SpaceAccessValidation {

    public final Mono<Boolean> readable(String spaceId){
        log.info("spaceId: {}", spaceId);
        Mono<Boolean> access = AuthUtils.getMemberDetailsMono()
                .map(memberDetails -> memberDetails.spaces()
                        .stream()
                        .anyMatch(o -> StringUtils.equals(o.id(), spaceId) && o.role().readable))
                .switchIfEmpty(AuthUtils.getAccessId()
                        .flatMap(accessId -> compareSpaceMemberRoleLevel(spaceId, accessId, SpaceRoleType.VIEWER))
                );
        return Mono.zip(access, spaceExist(spaceId), (a, b) -> a && b);
    }
}

AuthUtils用于从ReactiveSecurityContextHolder获取主体信息。但调用RestController接口时,传入的spaceId始终为null,接口代码如下:

@RestController
@RequestMapping("search/spaces/{spaceId}")
public class SearchRestController {

    @GetMapping("memos")
    @PreAuthorize("@SpaceAccess.readable(#spaceId)")
    @ResponseStatus(HttpStatus.OK)
    public Mono<PagingResultRecord> findMemos(@PathVariable(name = "spaceId") String spaceId){
        // 业务逻辑
    }
}

调用API时,SpEL表达式#spaceId始终传递null值,查阅文档确认动态传参用#variable是正确的,求解决办法。


解决方案

1. 编译时保留参数名称

Java默认编译会丢失方法参数名,导致SpEL无法识别#spaceId。需要在构建工具中开启-parameters编译选项:

  • Maven:在pom.xml的maven-compiler-plugin中添加配置
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.11.0</version>
    <configuration>
        <parameters>true</parameters>
        <source>17</source> <!-- 对应你的JDK版本 -->
        <target>17</target>
    </configuration>
</plugin>
  • Gradle:在build.gradle中添加
tasks.withType(JavaCompile) {
    options.parameters = true
}

2. 改用#root.args直接引用参数

在WebFlux的响应式方法安全场景下,直接引用参数名可能存在上下文传递问题,可以通过#root.args按索引获取参数:

修改接口的@PreAuthorize注解:

@PreAuthorize("@SpaceAccess.readable(#root.args[0])")

这里#root.args[0]对应方法的第一个参数,也就是spaceId。

3. 给参数添加@Param注解显式指定名称

在接口方法的参数上添加org.springframework.data.repository.query.Param注解,显式告诉SpEL参数的名称:

@GetMapping("memos")
@PreAuthorize("@SpaceAccess.readable(#spaceId)")
@ResponseStatus(HttpStatus.OK)
public Mono<PagingResultRecord> findMemos(
        @PathVariable(name = "spaceId") @Param("spaceId") String spaceId
){
    // 业务逻辑
}

4. 确认ReactiveMethodSecurity配置正确

确保已经在配置类上添加@EnableReactiveMethodSecurity注解,开启响应式方法安全支持:

@Configuration
@EnableReactiveMethodSecurity
public class SecurityConfig {
    // 其他安全配置
}

内容的提问来源于stack exchange,提问作者Cerakoted

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:53:11