Spring Boot中如何实现带参数的控制器方法权限校验注解?
实现Spring Boot控制器方法的权限校验注解
我来帮你一步步搞定这个需求,在Spring Boot环境下结合自定义注解和拦截器就能完美实现,具体步骤如下:
1. 完善自定义注解@ValidateAction的定义
首先确保你的注解符合Java规范,指定作用目标为方法且运行时可被反射获取:
import java.lang.annotation.*; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface ValidateAction { String resource(); String action(); }
(使用时写成@ValidateAction(resource = "resource", action = "release"),这种带属性名的写法更清晰规范)
2. 在拦截器中获取注解参数并校验权限
修改你已有的请求拦截器,在preHandle方法里定位到当前请求对应的Controller方法,提取注解参数后调用授权服务器做权限校验:
import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.access.AccessDeniedException; import org.springframework.web.client.RestTemplate; public class PermissionInterceptor implements HandlerInterceptor { private final RestTemplate restTemplate; // 通过构造注入RestTemplate用于调用授权服务器 public PermissionInterceptor(RestTemplate restTemplate) { this.restTemplate = restTemplate; } @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 先判断当前处理器是否是Controller方法 if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; // 获取方法上的@ValidateAction注解 ValidateAction validateAction = handlerMethod.getMethodAnnotation(ValidateAction.class); if (validateAction != null) { // 提取注解里的资源和操作参数 String resource = validateAction.resource(); String action = validateAction.action(); // 从请求头取出OAuth令牌(通常格式是Authorization: Bearer xxx) String authHeader = request.getHeader("Authorization"); if (authHeader == null || !authHeader.startsWith("Bearer ")) { throw new AccessDeniedException("缺少有效访问令牌"); } String accessToken = authHeader.substring(7); // 调用授权服务器校验权限 boolean hasPermission = checkPermission(accessToken, resource, action); if (!hasPermission) { throw new AccessDeniedException("你没有执行该操作的权限"); } } } // 没有注解或者校验通过,放行请求 return true; } // 封装调用授权服务器的逻辑 private boolean checkPermission(String accessToken, String resource, String action) { // 这里替换成你授权服务器的实际校验接口地址 String checkUrl = "http://your-auth-server/api/permission/check"; // 构造请求参数DTO PermissionCheckReq req = new PermissionCheckReq(accessToken, resource, action); // 发送请求并获取校验结果 Boolean result = restTemplate.postForObject(checkUrl, req, Boolean.class); // 处理空指针情况,默认返回无权限 return result != null && result; } // 内部类:权限校验请求参数 private static class PermissionCheckReq { private String accessToken; private String resource; private String action; public PermissionCheckReq(String accessToken, String resource, String action) { this.accessToken = accessToken; this.resource = resource; this.action = action; } // 省略getter/setter } }
3. 注册拦截器到Spring容器
最后要把拦截器配置到Spring Boot的WebMvc中,让它生效:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.client.RestTemplate; import org.springframework.web.servlet.config.annotation.InterceptorRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class WebConfig implements WebMvcConfigurer { @Bean public RestTemplate restTemplate() { return new RestTemplate(); } @Bean public PermissionInterceptor permissionInterceptor(RestTemplate restTemplate) { return new PermissionInterceptor(restTemplate); } @Override public void addInterceptors(InterceptorRegistry registry) { // 指定拦截的路径,比如拦截所有/api开头的请求,可根据你的业务调整 registry.addInterceptor(permissionInterceptor(restTemplate())) .addPathPatterns("/**"); } }
4. 在Controller方法上使用注解
现在就可以按照你期望的方式使用注解了:
@RequestMapping("/release") @ValidateAction(resource = "resource", action = "release") public ResponseEntity releaseSoftware(Request request){ // 你的业务逻辑代码 }
这样当请求到达该方法时,拦截器会自动提取注解参数,携带OAuth令牌调用授权服务器校验权限;如果校验不通过,会直接抛出AccessDeniedException,Spring Security会自动处理这个异常并返回对应的权限错误响应。
内容的提问来源于stack exchange,提问作者user09
相关产品推荐
相关产品推荐

