竹简文档
过滤器

权限过滤器

基于 @NeedPermission 注解的抽象权限校验过滤器

权限过滤器

权限过滤器是一个抽象过滤器类,提供基于 @NeedPermission 注解的权限校验框架。该过滤器在请求到达 Controller 之前检查目标方法是否标注了 @NeedPermission 注解,若标注则调用抽象方法执行实际的权限校验逻辑。

MVC vs WebFlux 对比

对比项MVC 版本WebFlux 版本
实现接口FilterWebFilter
类名PermissionFilterHandlerPermissionWebFilter
抽象方法hasPermissionCheck(HttpServletRequest, String)hasPermissionCheck(ServerWebExchange, String)
返回类型booleanMono<Void>
Handler 解析HandlerMapping.getHandler()ServerWebExchangeUtil.getHandlerMethod()

工作流程

HTTP 请求进入


解析目标 Handler 方法


检查是否标注 @NeedPermission

    ├── 未标注 → 直接放行

    └── 已标注 → 调用 hasPermissionCheck()

                ├── 校验通过 → 放行
                └── 校验失败 → 返回 403 Forbidden

@NeedPermission 注解

NeedPermission.java
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface NeedPermission {
    // 权限标识字符串
    String value();
}

抽象方法

仅 MVC

PermissionFilterHandler.java
// 子类必须实现此方法,完成实际的权限校验逻辑
protected abstract boolean hasPermissionCheck(
    HttpServletRequest request, String permission);

字段

类型

返回 true 表示放行,返回 false 表示拒绝访问。

仅 WebFlux

PermissionWebFilter.java
// 抽象方法,由子类实现具体的权限校验逻辑
protected abstract Mono<Void> hasPermissionCheck(
        ServerWebExchange exchange, String permission);

校验通过则正常完成 Mono,失败时应抛出异常或直接设置响应状态码。

实现示例

仅 MVC

ApiPermissionFilter.java
public class ApiPermissionFilter extends PermissionFilterHandler {

    private final PermissionService permissionService;

    public ApiPermissionFilter(
            HandlerMapping handlerMapping,
            PermissionService permissionService) {
        super(handlerMapping);
        this.permissionService = permissionService;
    }

    @Override
    protected boolean hasPermissionCheck(
            HttpServletRequest request, String permission) {
        // 从请求头中获取用户身份
        String token = request.getHeader("Authorization");
        if (token == null) {
            return false;
        }

        // 委托给权限服务校验
        String userId = tokenService.getUserId(token);
        return permissionService.hasPermission(userId, permission);
    }
}

注册过滤器:

FilterConfig.java
@Configuration
@RequiredArgsConstructor
public class FilterConfig {

    private final HandlerMapping handlerMapping;
    private final PermissionService permissionService;

    @Bean
    public FilterRegistrationBean<ApiPermissionFilter> permissionFilter() {
        FilterRegistrationBean<ApiPermissionFilter> registration =
            new FilterRegistrationBean<>();
        registration.setFilter(
            new ApiPermissionFilter(handlerMapping, permissionService));
        registration.addUrlPatterns("/api/*");
        registration.setOrder(10);
        return registration;
    }
}

仅 WebFlux

CustomPermissionFilter.java
// 继承 PermissionWebFilter 并实现 hasPermissionCheck 方法
@Component
public class CustomPermissionFilter extends PermissionWebFilter {

    private final PermissionService permissionService;

    public CustomPermissionFilter(PermissionService permissionService,
                                   RequestMappingHandlerMapping handlerMapping) {
        super(handlerMapping);
        this.permissionService = permissionService;
    }

    @Override
    // 实现具体的权限校验逻辑
    // 返回 Mono<Void>,校验通过则正常完成,失败则抛出异常
    protected Mono<Void> hasPermissionCheck(ServerWebExchange exchange, String permission) {
        String token = exchange.getRequest().getHeaders().getFirst("Authorization");
        return permissionService.checkPermission(token, permission)
                .flatMap(hasPermission -> {
                    if (!hasPermission) {
                        exchange.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
                        return exchange.getResponse().setComplete();
                    }
                    return Mono.empty();
                });
    }
}

使用注解标记接口

在 Controller 方法上标注 @NeedPermission 注解,声明该接口所需的权限:

AdminController.java
@RestController
@RequestMapping("/api/v1/admin")
public class AdminController {

    // 需要 "admin:user:manage" 权限
    @NeedPermission("admin:user:manage")
    @GetMapping("/users")
    public ResponseEntity<BaseResponse<List<UserVO>>> listUsers() {
        return ResultUtil.success("查询成功", userService.listAll());
    }

    // 需要 "admin:config:edit" 权限
    @NeedPermission("admin:config:edit")
    @PutMapping("/config")
    public ResponseEntity<BaseResponse<Void>> updateConfig(
            @RequestBody ConfigDTO dto) {
        configService.update(dto);
        return ResultUtil.success("更新成功");
    }

    // 未标注 @NeedPermission,无需权限校验
    @GetMapping("/public/info")
    public ResponseEntity<BaseResponse<InfoVO>> getPublicInfo() {
        return ResultUtil.success("查询成功", infoService.getPublic());
    }
}

注意事项

  • 权限过滤器是抽象类,不能直接使用,必须实现抽象方法
  • 过滤器需要 HandlerMapping 实例来解析请求对应的 Handler 方法及其注解
  • 权限校验在 Filter 层执行,早于 Controller 的 AOP 切面
  • 建议将权限标识设计为层级格式(如 module:resource:action),便于管理
  • 该过滤器不由自动配置注册,需开发者自行将实现类注册为 Spring Bean

下一步

On this page