在Spring Boot项目中实现用户查询数据权限控制
本文介绍了在Spring Boot项目中实现用户查询数据权限控制的系统方案。通过权限元数据建模建立数据权限规则表,结合MyBatis拦截器动态改写SQL语句。方案包含规则引擎解析器、AOP权限校验增强、多租户隔离等核心模块,并提供了缓存优化和实施建议。该设计采用分层架构,从基础数据模型到上层应用拦截,实现了灵活、安全的权限控制,同时保持系统性能稳定。实施路径建议分阶段推进,并强调了防御性编程和安全
·
一、权限元数据建模
- 权限维度抽象
- 建立数据权限矩阵表(data_permission_matrix)
CREATE TABLE data_permission_rule (
id BIGINT PRIMARY KEY,
role_code VARCHAR(32) NOT NULL, -- 角色标识
resource_type VARCHAR(64) NOT NULL, -- 资源类型(如订单、客户)
condition_type ENUM('SELF','DEPT','CUSTOM') NOT NULL, -- 条件类型
condition_expression VARCHAR(512) -- SQL条件表达式
);
- 用户上下文封装
public class UserContext {
private Long userId;
private String deptId;
private Set<String> roles;
// 附加属性:岗位、区域等
}
二、动态条件拦截器
- MyBatis拦截器实现
@Intercepts({@Signature(type = Executor.class, method = "query",
args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
public class DataPermissionInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
// 1. 解析当前用户上下文
UserContext user = SecurityUtils.getCurrentUser();
// 2. 获取Mapper绑定的资源类型
MappedStatement ms = (MappedStatement) invocation.getArgs()[0];
String resourceType = parseResourceType(ms.getId());
// 3. 查询权限规则集
List<DataPermissionRule> rules = ruleService.getRules(user.getRoles(), resourceType);
// 4. 构建动态WHERE条件
String dynamicCondition = buildCondition(rules, user);
// 5. 改写原始SQL
BoundSql boundSql = ms.getBoundSql(invocation.getArgs()[1]);
String newSql = boundSql.getSql() + " AND " + dynamicCondition;
// 6. 创建新BoundSql继续执行
// ... 具体实现省略
}
}
三、规则引擎设计
- 条件表达式解析器
public class ConditionParser {
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("\\$\\{(\\w+)\\}");
public static String parse(String template, UserContext user) {
Matcher matcher = PLACEHOLDER_PATTERN.matcher(template);
StringBuffer sb = new StringBuffer();
while (matcher.find()) {
String key = matcher.group(1);
String value = getValueFromUser(key, user);
matcher.appendReplacement(sb, value);
}
matcher.appendTail(sb);
return sb.toString();
}
private static String getValueFromUser(String key, UserContext user) {
switch (key) {
case "userId": return user.getUserId().toString();
case "deptId": return user.getDeptId();
case "roleCodes": return String.join(",", user.getRoles());
default: throw new IllegalArgumentException("未知占位符: " + key);
}
}
}
四、服务层整合
- AOP权限校验增强
@Aspect
@Component
public class DataPermissionAspect {
@Pointcut("@annotation(com.example.anno.DataPermission)")
public void dataPermissionPointcut() {}
@Around("dataPermissionPointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 1. 解析方法注解获取资源类型
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
DataPermission annotation = signature.getMethod().getAnnotation(DataPermission.class);
// 2. 将资源类型存储到ThreadLocal
DataPermissionContext.setResourceType(annotation.value());
try {
return joinPoint.proceed();
} finally {
DataPermissionContext.clear();
}
}
}
五、多租户扩展设计
- 租户隔离方案
- 通过TenantID自动注入
public class TenantContext {
private static final ThreadLocal<String> CURRENT_TENANT = new ThreadLocal<>();
public static void setTenantId(String tenantId) {
CURRENT_TENANT.set(tenantId);
}
public static String getTenantId() {
return CURRENT_TENANT.get();
}
}
// 在拦截器中自动追加条件
String tenantCondition = "tenant_id = '" + TenantContext.getTenantId() + "'";
六、缓存优化策略
- 规则缓存设计
@Cacheable(value = "permissionRules", key = "#roleCodes.concat(#resourceType)")
public List<DataPermissionRule> getRules(Set<String> roleCodes, String resourceType) {
// 数据库查询逻辑
}
实施建议:
-
渐进式实施路径
- Phase1:硬编码基础过滤条件
- Phase2:动态SQL改写基础版
- Phase3:完整规则引擎实现
- Phase4:可视化规则配置界面
-
监控指标
@Data
public class DataPermissionMetrics {
private int sqlRewriteCount; // SQL改写次数
private int ruleHitCount; // 规则命中次数
private Map<String, Integer> resourceAccessStats; // 资源访问统计
}
- 防御性编程要点
- SQL注入防护:对用户输入参数严格校验
- 兜底策略:默认开启全量数据保护模式
- 审计日志:记录原始SQL与改写后SQL
该方案通过多层级联动控制,实现了从用户属性到SQL语句的动态转换,既保证了权限控制的灵活性,又维持了系统性能的稳定性。建议配合Apollo等配置中心实现规则的动态热更新,并定期进行权限矩阵验证测试。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)