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

能否复用RestController/RequestMapping实现HTTP请求授权?

借助RestController类实现Spring Security授权控制(复用RequestMapping配置)

完全可以实现类似Spring Boot Actuator中EndpointRequest的效果,通过RestController类直接配置授权规则,无需重复编写路径字符串。Spring Security本身没有提供现成的API,但可以通过解析Controller的@RequestMapping注解自定义请求匹配器,复用已有配置。

实现步骤与代码示例

1. 自定义Controller请求匹配器

创建一个RequestMatcher实现类,负责解析Controller类和方法上的@RequestMapping(及其派生注解如@GetMapping),生成对应的路径和请求方法匹配规则:

import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import jakarta.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class ControllerRequestMatcher implements RequestMatcher {

    private final List<RequestMatcher> matchers = new ArrayList<>();

    public ControllerRequestMatcher(Class<?>... controllerClasses) {
        for (Class<?> controllerClass : controllerClasses) {
            // 解析类级@RequestMapping
            RequestMapping classMapping = AnnotationUtils.findAnnotation(controllerClass, RequestMapping.class);
            if (classMapping == null) continue;

            String[] basePaths = classMapping.value();
            RequestMethod[] allowedMethods = classMapping.method().length > 0 ? classMapping.method() : RequestMethod.values();

            // 解析方法级@RequestMapping(含派生注解)
            Set<RequestMapping> methodMappings = AnnotationUtils.findRepeatableAnnotations(controllerClass, RequestMapping.class);
            if (methodMappings.isEmpty()) {
                // 无方法级注解时,直接使用类级路径和方法
                for (String basePath : basePaths) {
                    for (RequestMethod method : allowedMethods) {
                        matchers.add(new AntPathRequestMatcher(basePath, method.name()));
                    }
                }
                continue;
            }

            // 组合类和方法的路径与请求方法
            for (String basePath : basePaths) {
                for (RequestMapping methodMapping : methodMappings) {
                    String[] methodPaths = methodMapping.value();
                    RequestMethod[] methodSpecificMethods = methodMapping.method().length > 0 ? methodMapping.method() : allowedMethods;

                    for (String methodPath : methodPaths) {
                        String fullPath = combinePaths(basePath, methodPath);
                        for (RequestMethod method : methodSpecificMethods) {
                            matchers.add(new AntPathRequestMatcher(fullPath, method.name()));
                        }
                    }
                }
            }
        }
    }

    // 拼接类和方法的路径,处理斜杠重复问题
    private String combinePaths(String basePath, String methodPath) {
        if (basePath.endsWith("/") && methodPath.startsWith("/")) {
            return basePath + methodPath.substring(1);
        }
        if (!basePath.endsWith("/") && !methodPath.startsWith("/")) {
            return basePath + "/" + methodPath;
        }
        return basePath + methodPath;
    }

    @Override
    public boolean matches(HttpServletRequest request) {
        return matchers.stream().anyMatch(matcher -> matcher.matches(request));
    }
}

2. 封装工具类简化调用

模仿Actuator的EndpointRequest,封装静态方法让配置更简洁:

public class ControllerRequest {
    public static ControllerRequestMatcher to(Class<?>... controllerClasses) {
        return new ControllerRequestMatcher(controllerClasses);
    }
}

3. 在Security配置中使用

直接通过Controller类配置授权规则,无需编写路径字符串:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests(auth -> auth
                // 授权指定Controller的所有请求无需认证
                .requestMatchers(ControllerRequest.to(MyPublicRestController.class))
                .permitAll()
                // 其他请求需要认证
                .anyRequest()
                .authenticated()
        );
        return http.build();
    }
}

关键特性说明

  • 自动解析@RequestMapping及其派生注解(@GetMapping、@PostMapping等),覆盖所有请求方法和路径配置
  • 支持类级和方法级注解的路径组合,自动处理斜杠重复问题
  • 复用Controller的现有配置,避免路径字符串重复编写,降低维护成本
  • 匹配规则与AntPathMatcher完全兼容,支持路径变量、通配符等语法

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 00:22:09