深入理解 AntPathMatcher 与基于权限表的 RBAC 鉴权机制
在 Spring 生态中,RBAC(基于角色的访问控制)是一种常见的权限管理机制。通常,我们会想到使用 Spring Security 来实现,但有些场景下,我们可能选择自定义权限表并结合一些工具来实现更灵活的权限校验。今天,我将详细讲解一种轻量级的路径匹配工具 —— AntPathMatcher,并结合一个实际的鉴权接口代码,带你理解它的原理和应用。
一、什么是 AntPathMatcher?
AntPathMatcher 是 Spring 提供的一个工具类,位于 org.springframework.util 包中。它的主要功能是基于 Ant 风格的路径匹配规则,判断两个路径字符串是否匹配。简单来说,它可以用来匹配 URL 或者文件路径,支持通配符,特别适合在权限校验中判断某个请求的 URI 是否符合预定义的规则。
Ant 风格路径规则
AntPathMatcher 支持以下三种通配符:
?:匹配单个字符。- 例如:
/user/?可以匹配/user/a或/user/1,但不匹配/user/ab。
- 例如:
*:匹配零个或多个字符(不包括路径分隔符/)。- 例如:
/user/*可以匹配/user/info或/user/123,但不匹配/user/info/detail。
- 例如:
**:匹配零个或多个路径段(包括路径分隔符/)。- 例如:
/user/**可以匹配/user/info、/user/info/detail或/user。
- 例如:
典型使用场景
在权限管理中,我们通常需要判断某个请求的 URI(例如 /api/user/info)是否符合权限规则(例如 /api/user/**)。AntPathMatcher 提供了一个简单而强大的方法来实现这种匹配。
二、结合代码理解 AntPathMatcher 在 RBAC 中的应用
下面,我们来看一段实际的代码。这是一个基于自定义权限表和 AntPathMatcher 实现的鉴权接口,来自一个 Feign 客户端的控制器类(PermissionFeignController)。我将逐步拆解它的逻辑,并说明 AntPathMatcher 在其中的作用。
代码概览
@RestController
public class PermissionFeignController implements PermissionFeignClient {
@Autowired
private MenuPermissionService menuPermissionService;
@Override
public ServerResponseEntity<Boolean> checkPermission(
@RequestParam("userId") Long userId,
@RequestParam("sysType") Integer sysType,
@RequestParam("uri") String uri,
@RequestParam("isAdmin") Integer isAdmin,
@RequestParam("method") Integer method) {
// 获取用户当前拥有的权限列表
List<String> userPermissions = menuPermissionService.listUserPermissions(
userId, sysType, BooleanUtil.isTrue(isAdmin));
// 获取系统中所有 URI 对应的权限规则
List<UriPermissionBO> uriPermissions = menuPermissionService.listUriPermissionInfo(sysType);
// 创建 AntPathMatcher 实例
AntPathMatcher pathMatcher = new AntPathMatcher();
// 遍历所有 URI 权限规则,匹配请求的 URI 和方法
for (UriPermissionBO uriPermission : uriPermissions) {
if (pathMatcher.match(uriPermission.getUri(), uri)
&& Objects.equals(uriPermission.getMethod(), method)) {
// 如果用户拥有该 URI 对应的权限,则校验通过
if (userPermissions.contains(uriPermission.getPermission())) {
return ServerResponseEntity.success(Boolean.TRUE);
} else {
return ServerResponseEntity.fail(ResponseEnum.UNAUTHORIZED);
}
}
}
// 如果没有匹配到任何规则,说明该 URI 无需权限,直接通过
return ServerResponseEntity.success(Boolean.TRUE);
}
// 清理用户权限缓存的方法(略)
}
代码逻辑拆解
-
输入参数:
userId:当前用户的 ID。sysType:系统类型,用于区分不同的业务模块。uri:请求的 URI,例如/api/user/info。isAdmin:是否为管理员(0 或 1)。method:HTTP 请求方法(如 GET=1、POST=2)。
-
获取权限数据:
listUserPermissions:根据用户 ID、系统类型和管理员状态,查询用户拥有的权限列表(List<String>),例如["user:read", "order:write"]。listUriPermissionInfo:查询系统中所有 URI 的权限规则(List<UriPermissionBO>)。UriPermissionBO可能包含字段如uri(规则路径)、method(请求方法)、permission(所需权限)。
-
路径匹配与权限校验:
- 使用
AntPathMatcher的match方法,比较请求的uri是否符合某个权限规则的uriPermission.getUri()。 - 同时检查请求的
method是否匹配规则中的method。 - 如果匹配成功,检查用户权限列表中是否包含规则要求的权限(
uriPermission.getPermission())。
- 使用
-
返回结果:
- 如果匹配到规则且用户有权限,返回
true。 - 如果匹配到规则但用户无权限,返回
UNAUTHORIZED。 - 如果没有匹配到任何规则,默认认为该 URI 无需权限,返回
true。
- 如果匹配到规则且用户有权限,返回
AntPathMatcher 的作用
在上述代码中,AntPathMatcher 的核心作用是实现 URI 的模糊匹配。例如:
- 权限规则的 URI 是
/api/user/**,而请求的 URI 是/api/user/info/detail。 pathMatcher.match("/api/user/**", "/api/user/info/detail")返回true,表示匹配成功。
这种匹配方式非常灵活,支持通配符规则,比简单的字符串相等(equals)更适合复杂的路径校验场景。
三、为什么不用 Spring Security,选择自定义实现?
优点
- 轻量级:不引入 Spring Security 这样的大型框架,减少了依赖和学习成本。
- 灵活性高:权限表完全自定义,可以根据业务需求调整字段和逻辑。
- 易于调试:逻辑清晰,开发者可以直接控制校验流程。
缺点
- 功能有限:相比 Spring Security,缺少开箱即用的功能(如 CSRF 保护、会话管理)。
- 安全性风险:需要自己确保代码逻辑无漏洞,例如默认放行的设计可能不够严谨。
- 维护成本:随着系统复杂度增加,自定义实现可能需要更多代码来支持新需求。