前一篇已经分析了多种权限模型,其中比较常用的是基于角色的权限控制。
基于角色的权限控制
表设计:
用户表
用户--角色关系表
角色表
角色--菜单关系表
菜单表
权限标识格式:
格式: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)
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)
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、路径等可配置,适应不同项目
- 默认实现:提供常用实现,开箱即用
按照以上设计思路,可实现一个通用、灵活、易用的权限控制框架。