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

如何通过编程获取指定VERB+PATH端点@PreAuthorize注解中的SpEL?

当然可以!在Spring生态环境下,我们完全可以通过编程手段提取指定请求端点上@PreAuthorize注解中的SpEL表达式,下面是具体的实现思路和代码示例:

核心思路

Spring Security的@PreAuthorize注解通常标注在控制器方法或类上,而Spring的RequestMappingHandlerMapping组件会维护所有请求映射与处理器方法的关联关系。我们的核心逻辑就是:找到对应请求方式(VERB)和路径(PATH)的处理器方法,再从方法或其所在类上提取@PreAuthorize的SpEL内容。

具体实现步骤与代码示例

下面以Spring Boot环境为例,写一个可直接复用的提取工具类:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.lang.reflect.Method;
import java.util.Set;

@Component
public class PreAuthorizeSpelExtractor {

    private final RequestMappingHandlerMapping requestMappingHandlerMapping;

    @Autowired
    public PreAuthorizeSpelExtractor(RequestMappingHandlerMapping requestMappingHandlerMapping) {
        this.requestMappingHandlerMapping = requestMappingHandlerMapping;
    }

    public String extractSpelForEndpoint(RequestMethod requestMethod, String path) {
        // 构造目标请求的映射信息,用于匹配端点
        RequestMappingInfo targetMapping = RequestMappingInfo.paths(path)
                .methods(requestMethod)
                .build();

        // 遍历所有已注册的请求映射
        Set<RequestMappingInfo> allMappings = requestMappingHandlerMapping.getHandlerMethods().keySet();
        for (RequestMappingInfo mapping : allMappings) {
            if (mapping.equals(targetMapping)) {
                // 获取对应的处理器方法(这里默认取第一个匹配的方法,多实例场景可按需调整)
                Method handlerMethod = requestMappingHandlerMapping.getHandlerMethods().get(mapping).get(0).getMethod();
                
                // 优先检查方法上的@PreAuthorize注解
                PreAuthorize methodAnnotation = handlerMethod.getAnnotation(PreAuthorize.class);
                if (methodAnnotation != null) {
                    return methodAnnotation.value();
                }
                
                // 方法上没有的话,检查类级别的注解
                PreAuthorize classAnnotation = handlerMethod.getDeclaringClass().getAnnotation(PreAuthorize.class);
                if (classAnnotation != null) {
                    return classAnnotation.value();
                }
                
                break;
            }
        }

        // 未找到注解时返回null,也可根据需求返回空字符串
        return null;
    }
}
关键说明
  • 匹配精度:如果你的应用存在多个匹配同一路径但不同produces/consumes的端点,示例中只取第一个匹配项,实际使用时可以通过RequestMappingInfo的其他属性(如producesCondition)做更精确的过滤;
  • 类级别注解:代码中会先检查方法上的注解,再检查类上的——因为方法级别的注解优先级高于类级别;
  • WebFlux适配:如果是Spring WebFlux项目,只需替换为org.springframework.web.reactive.result.method.annotation.RequestMappingHandlerMapping,核心逻辑完全一致;
  • 动态端点:如果是运行时动态注册的端点,需要确保在端点注册完成后再调用这个工具方法,否则可能无法匹配到。

这样就能轻松拿到指定端点的@PreAuthorize SpEL表达式了,要是你有特殊场景需要调整,随时可以基于这个核心逻辑扩展~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:01:47