前一篇已经分析了多种权限模型控制权限系列之(1)模型分析梳理,其中比较常用的是基于角色的权限控制。
基于角色的权限控制的表设计:
用户表 角色表 菜单表用户--角色关系表 角色--菜单关系表
权限标识格式:
格式:xxx:xxx:xxx(模块:资源:操作)
权限架构的分层结构:
应用层 (@RequirePermission注解)↓ 权限验证层 (PermissionValidator)↓ 权限上下文层 (PermissionContext - ThreadLocal)↓ 权限提供层 (PermissionProvider - 数据库/缓存)↓ 权限存储层 (PermissionStorage - Redis/Memory)
权限架构接口:
权限提供者接口 (PermissionProvider)
从数据源获取用户权限数据
1 public interface PermissionProvider { 2 // 获取用户的所有权限标识 3 Set<String> getUserPermissions(Object userId); 4 5 // 获取用户角色列表 6 Set<String> getUserRoles(Object userId); 7 8 // 检查用户是否为超级管理员 9 boolean isSuperAdmin(Object userId); 10 11 // 刷新用户权限缓存 12 void refreshUserPermissions(Object userId); 13 }
userId使用Object类型,支持 String、Long 等不同ID类型- 支持超级管理员逻辑(拥有所有权限)
- 提供刷新接口,支持权限变更后更新缓存
权限存储接口 (PermissionStorage)
权限数据的存储和读取(Token、Redis、Memory等)
1 public interface PermissionStorage { 2 // 存储用户权限信息 3 void storeUserInfo(String token, UserInfo userInfo); 4 5 // 获取用户权限信息 6 UserInfo getUserInfo(String token); 7 8 // 删除用户权限信息 9 void removeUserInfo(String token); 10 11 // 刷新用户权限信息 12 void refreshUserInfo(String token, UserInfo userInfo); 13 }
- 基于Token存储,支持分布式场景
- 支持多种存储实现(Redis、Memory、数据库等)
- 提供刷新接口,支持权限实时更新
权限匹配器接口 (PermissionMatcher)
权限匹配策略(精确匹配、通配符匹配等)
1 public interface PermissionMatcher { 2 // 匹配权限 3 boolean match(String requiredPermission, Set<String> userPermissions); 4 5 // 批量匹配(全部满足) 6 boolean matchAll(Set<String> requiredPermissions, Set<String> userPermissions); 7 8 // 批量匹配(任意一个满足) 9 boolean matchAny(Set<String> requiredPermissions, Set<String> userPermissions); 10 }
- 支持多种匹配策略(精确、通配符、正则等)
- 支持批量匹配(AND/OR逻辑)
- 可扩展自定义匹配规则
用户信息
1 public class UserInfo { 2 private Object userId; // 用户ID 3 private String username; // 用户名 4 private Set<String> permissions; // 权限集合 5 private Set<String> roles; // 角色集合 6 private boolean superAdmin; // 是否超级管理员 7 private Map<String, Object> attributes; // 扩展属性 8 }
- 使用
Object类型支持不同ID类型 - 提供扩展属性,支持业务字段存储
- 轻量级设计,便于序列化和传输
权限上下文 (PermissionContext)
基于ThreadLocal的权限上下文管理
1 public class PermissionContext { 2 private static final ThreadLocal<UserInfo> USER_INFO_HOLDER = new TransmittableThreadLocal<>(); 4 5 public static void set(UserInfo userInfo); 6 public static UserInfo get(); 7 public static void clear(); 8 9 public static boolean hasPermission(String permission); 10 public static Set<String> getPermissions(); 11 }
- 使用
TransmittableThreadLocal支持线程池传递 - 提供便捷方法,简化权限判断
- 请求结束后自动清理,避免内存泄漏
权限验证器接口 (PermissionValidator)
权限验证逻辑
1 public interface PermissionValidator { 2 // 验证单个权限 3 boolean hasPermission(String permission); 4 5 // 验证所有权限(AND) 6 boolean hasAllPermissions(Set<String> permissions); 7 8 // 验证任意权限(OR) 9 boolean hasAnyPermission(Set<String> permissions); 10 11 // 验证角色 12 boolean hasRole(String role); 13 14 // 获取当前用户上下文 15 UserContext getCurrentUser(); 16 }
- 提供多种验证方式(单个、全部、任意)
- 支持角色验证
- 统一权限验证入口
实现策略
数据库权限获取
- 通过JdbcTemplate执行SQL查询
- SQL可配置化(支持不同数据库表结构)
- 支持超级管理员特殊处理
- 支持权限缓存
1 @Component 2 public class DatabasePermissionProvider implements PermissionProvider { 3 4 @Override 5 public Set<String> getUserPermissions(Object userId) { 6 // 1. 检查是否为超级管理员 7 if (isSuperAdmin(userId)) { 8 return getAllPermissions(); // 返回所有权限 9 } 10 11 // 2. 查询用户权限(通过用户-角色-菜单关联) 12 List<String> permsList =userService.getPermissions();19 20 // 3. 返回权限集合 21 return permsList; 27 } 28 }
抽象权限提供者 (AbstractPermissionProvider)
- 提供模板方法,定义权限获取流程
- 子类只需实现具体查询逻辑
- 统一处理超级管理员逻辑
1 public abstract class AbstractPermissionProvider implements PermissionProvider { 2 3 @Override 4 public Set<String> getUserPermissions(Object userId) { 5 // 方法:统一处理超管 6 if (isSuperAdmin(userId)) { 7 return getAllPermissions(); 8 } 9 return doGetUserPermissions(userId); 10 } 11 12 // 子类实现:获取所有权限 13 protected abstract Set<String> getAllPermissions(); 14 15 // 子类实现:查询用户权限 16 protected abstract Set<String> doGetUserPermissions(Object userId); 17 }
Redis存储 (RedisPermissionStorage)
- 使用Redis存储用户信息(JSON序列化)
- 支持过期时间配置
- 支持Key前缀配置
- 异常处理和日志记录
1 public class RedisPermissionStorage implements PermissionStorage { 2 3 @Override 4 public void storeUserInfo(String token, UserInfo userInfo) { 7 redisTemplate.opsForValue().set(key, value, expireSeconds, TimeUnit.SECONDS); 8 } 9 10 @Override 11 public UserInfo getUserInfo(String token) {14 return value; 15 } 16 }
通配符匹配器 (WildcardPermissionMatcher)
- 支持
*和?通配符 - 例如:
sys:user:*匹配sys:user:save、sys:user:update等 - 使用Spring的
PatternMatchUtils.simpleMatch()
权限过滤器实现
- 请求头提取Token
- 从Storage获取用户信息(如不存在,从Provider加载)
- 设置到PermissionContext
- 请求结束后清理上下文
过滤器流程:
请求到达↓
检查排除路径(登录、公开接口等)↓
提取Token↓
从Storage获取用户信息↓(如果不存在)
从Provider加载用户信息 → 存储到Storage↓
设置到PermissionContext↓
继续请求处理↓
清理PermissionContext
权限注解 (@RequirePermission)
- 支持单个权限、多个权限(AND/OR)
- 支持角色验证
- 支持自定义错误消息
@Target({ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface RequirePermission {String value() default ""; // 单个权限String[] all() default {}; // 全部权限(AND)String[] any() default {}; // 任意权限(OR)String role() default ""; // 单个角色String message() default "权限不足"; // 错误消息 }
AOP切面实现
- 拦截
@RequirePermission注解的方法 - 从PermissionContext获取用户信息
- 调用PermissionValidator验证权限
- 验证失败抛出异常
1 @Aspect 2 public class PermissionAspect { 3 4 @Before("@annotation(RequirePermission)") 5 public void checkPermission(JoinPoint joinPoint) { 6 RequirePermission annotation = getAnnotation(joinPoint); 7 8 // 验证权限 9 if (!permissionValidator.hasPermission(annotation.value())) { 10 throw new PermissionDeniedException(annotation.message()); 11 } 12 } 13 }
与SpringBoot项目集成
配置类设计:
- 自动配置各个组件
- 支持条件装配(@ConditionalOnMissingBean)
- 提供默认实现
1 @Configuration 2 @EnableConfigurationProperties(PermissionProperties.class) 3 public class PermissionAutoConfiguration { 4 5 @Bean 6 @ConditionalOnMissingBean 7 public PermissionMatcher permissionMatcher() { 8 return new WildcardPermissionMatcher(); 9 } 10 11 @Bean 12 @ConditionalOnMissingBean 13 public PermissionValidator permissionValidator(PermissionMatcher matcher) { 14 return new DefaultPermissionValidator(matcher); 15 } 16 17 @Bean 18 @ConditionalOnMissingBean 19 public PermissionFilter permissionFilter(...) { 20 return new PermissionFilter(...); 21 } 22 }
使用示例:
1 @RestController 2 @RequestMapping("/api/user") 3 public class UserController { 4 5 // 单个权限验证 6 @GetMapping("/list") 7 @RequirePermission("sys:user:list") 8 public ResponseEntity<List<User>> list() { 9 return ResponseEntity.ok(userService.list()); 10 } 11 12 // 多个权限(全部满足) 13 @PutMapping("/{id}") 14 @RequirePermission(all = {"sys:user:update", "sys:user:edit"}) 15 public ResponseEntity<Void> update(@PathVariable Long id, @RequestBody User user) { 16 userService.update(id, user); 17 return ResponseEntity.ok().build(); 18 } 19 20 // 多个权限(任意一个) 21 @DeleteMapping("/{id}") 22 @RequirePermission(any = {"sys:user:delete", "sys:user:remove"}) 23 public ResponseEntity<Void> delete(@PathVariable Long id) { 24 userService.delete(id); 25 return ResponseEntity.ok().build(); 26 } 27 28 // 角色验证 29 @GetMapping("/admin") 30 @RequirePermission(role = "ADMIN") 31 public ResponseEntity<String> adminOnly() { 32 return ResponseEntity.ok("Admin only"); 33 } 34 }
代码逻辑使用:
1 @Service 2 public class UserService { 3 4 @Autowired 5 private PermissionValidator permissionValidator; 6 7 public void deleteUser(Long userId) { 8 9 if (!permissionValidator.hasPermission("sys:user:delete")) { 10 throw new PermissionDeniedException("无删除权限"); 11 } 12 13 userRepository.delete(userId); 14 } 15 16 public UserContext getCurrentUser() { 17 return permissionValidator.getCurrentUser(); 18 } 19 }
总结:
- 接口抽象:所有核心功能都通过接口定义,便于扩展
- 分层设计:Provider → Storage → Matcher → Validator,职责清晰
- 上下文管理:使用ThreadLocal,支持异步场景
- 配置化:SQL、路径等可配置,适应不同项目
- 默认实现:提供常用实现,开箱即用
按照以上设计思路,可以逐步实现一个通用、灵活、易用的权限控制框架。