前一篇已经分析了多种权限模型,其中比较常用的是基于角色的权限控制。
基于角色的权限控制
表设计:
- 用户表
- 用户--角色关系表
- 角色表
- 角色--菜单关系表
- 菜单表
复制代码 权限标识格式:
- 格式:xxx:xxx:xxx(模块:资源:操作) 三段式
复制代码 权限架构的分层结构:
- 应用层 (@RequirePermission注解)
- ↓
- 权限验证层 (PermissionValidator)
- ↓
- 权限上下文层 (PermissionContext - ThreadLocal)
- ↓
- 权限提供层 (PermissionProvider - 数据库/缓存)
- ↓
- 权限存储层 (PermissionStorage - Redis/Memory)
复制代码
权限架构接口:
权限提供者接口
- 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类型
- 支持超级管理员逻辑(拥有所有权限)
- 提供刷新接口,支持权限变更后更新缓存
权限存储接口
- 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、数据库等)
- 提供刷新接口,支持权限实时更新
权限匹配器接口
- 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类型
- 提供扩展属性,支持业务字段存储
- 轻量级设计,便于序列化和传输
权限上下文
- 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 支持线程池传递
- 提供便捷方法,简化权限判断
- 请求结束后自动清理,避免内存泄漏
权限验证器接口
- 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 }
复制代码
- 提供多种验证方式(单个、全部、任意)
- 支持角色验证
- 统一权限验证入口
实现策略
抽象权限提供者
- 提供模板方法,定义权限获取流程
- 子类只需实现具体查询逻辑
- 统一处理超级管理员逻辑
- 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存储
- 使用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 }
复制代码
- 支持 * 和 ? 通配符
- 例如:sys:user:* 匹配 sys:user:save、sys:user:update 等
- 使用Spring的 PatternMatchUtils.simpleMatch()
权限过滤器
- 请求头提取Token
- 从Storage获取用户信息(如不存在,从Provider加载)
- 设置到PermissionContext
- 请求结束后清理上下文
- <strong>过滤器流程:</strong><br><br>请求到达
- ↓
- 检查排除路径(登录、公开接口等)
- ↓
- 提取Token
- ↓
- 从Storage获取用户信息
- ↓(如果不存在)
- 从Provider加载用户信息 → 存储到Storage
- ↓
- 设置到PermissionContext
- ↓
- 继续请求处理
- ↓
- 清理PermissionContext
复制代码 权限注解
- 支持单个权限、多个权限(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、路径等可配置,适应不同项目
- 默认实现:提供常用实现,开箱即用
按照以上设计思路,可实现一个灵活易用的权限控制框架。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |