|
|
@@ -1,15 +1,16 @@
|
|
|
package com.payment.platform.core.permission;
|
|
|
|
|
|
-import com.baomidou.mybatisplus.core.toolkit.PluginUtils;
|
|
|
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
|
|
|
import com.payment.platform.core.security.LoginUser;
|
|
|
+import com.payment.platform.module.system.dept.service.DeptService;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import net.sf.jsqlparser.expression.Expression;
|
|
|
import net.sf.jsqlparser.expression.LongValue;
|
|
|
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
|
|
|
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
|
|
|
import net.sf.jsqlparser.expression.operators.relational.InExpression;
|
|
|
-import net.sf.jsqlparser.expression.operators.relational.ItemsList;
|
|
|
+import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
|
|
|
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
|
|
|
import net.sf.jsqlparser.schema.Column;
|
|
|
import net.sf.jsqlparser.statement.Statement;
|
|
|
@@ -17,7 +18,6 @@ import net.sf.jsqlparser.statement.select.PlainSelect;
|
|
|
import net.sf.jsqlparser.statement.select.Select;
|
|
|
import net.sf.jsqlparser.statement.select.SelectBody;
|
|
|
import org.apache.ibatis.executor.Executor;
|
|
|
-import org.apache.ibatis.executor.statement.StatementHandler;
|
|
|
import org.apache.ibatis.mapping.BoundSql;
|
|
|
import org.apache.ibatis.mapping.MappedStatement;
|
|
|
import org.apache.ibatis.session.ResultHandler;
|
|
|
@@ -26,7 +26,6 @@ import org.springframework.security.core.Authentication;
|
|
|
import org.springframework.security.core.context.SecurityContextHolder;
|
|
|
import org.springframework.stereotype.Component;
|
|
|
|
|
|
-import java.sql.Connection;
|
|
|
import java.util.List;
|
|
|
|
|
|
/**
|
|
|
@@ -35,21 +34,26 @@ import java.util.List;
|
|
|
*
|
|
|
* 策略:
|
|
|
* - data_scope=1: WHERE created_id = currentUserId
|
|
|
- * - data_scope=2: WHERE dept_id = currentDeptId
|
|
|
- * - data_scope=3: WHERE dept_id IN (currentDeptId + children)
|
|
|
+ * - data_scope=2: WHERE dept_id = userDeptId
|
|
|
+ * - data_scope=3: WHERE dept_id IN (userDeptId + child dept IDs)
|
|
|
* - data_scope=4/5: 不追加(全部数据 或 自定义由业务层处理)
|
|
|
*/
|
|
|
@Slf4j
|
|
|
@Component
|
|
|
+@RequiredArgsConstructor
|
|
|
public class DataScopeInnerInterceptor implements InnerInterceptor {
|
|
|
|
|
|
/**
|
|
|
- * 需要数据权限过滤的表
|
|
|
+ * 需要数据权限过滤的表 — 系统表 + 支付业务表
|
|
|
*/
|
|
|
private static final List<String> DATA_SCOPE_TABLES = List.of(
|
|
|
- "sys_user", "sys_dept", "sys_role", "sys_log"
|
|
|
+ "sys_user", "sys_dept", "sys_role", "sys_log",
|
|
|
+ "pay_department", "pay_employee", "pay_transfer", "pay_bill",
|
|
|
+ "pay_expense_quota", "pay_deposit", "pay_withdraw", "pay_account"
|
|
|
);
|
|
|
|
|
|
+ private final DeptService deptService;
|
|
|
+
|
|
|
@Override
|
|
|
public void beforeQuery(Executor executor, MappedStatement ms, Object parameter,
|
|
|
RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
|
|
|
@@ -58,10 +62,14 @@ public class DataScopeInnerInterceptor implements InnerInterceptor {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 管理员不限制
|
|
|
+ // 管理员或 data_scope=4(全部)不限制
|
|
|
if (user.getIsSuperuser() != null && user.getIsSuperuser()) {
|
|
|
return;
|
|
|
}
|
|
|
+ Integer dataScope = user.getDataScope();
|
|
|
+ if (dataScope == null || dataScope == 4 || dataScope == 5) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
String originalSql = boundSql.getSql();
|
|
|
try {
|
|
|
@@ -80,10 +88,8 @@ public class DataScopeInnerInterceptor implements InnerInterceptor {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // data_scope=1 → 仅本人数据
|
|
|
- Expression scopeCondition = new EqualsTo(
|
|
|
- new Column("created_id"),
|
|
|
- new LongValue(user.getUserId()));
|
|
|
+ Expression scopeCondition = buildScopeCondition(dataScope, user);
|
|
|
+ if (scopeCondition == null) return;
|
|
|
|
|
|
if (plainSelect.getWhere() == null) {
|
|
|
plainSelect.setWhere(scopeCondition);
|
|
|
@@ -91,12 +97,38 @@ public class DataScopeInnerInterceptor implements InnerInterceptor {
|
|
|
plainSelect.setWhere(new AndExpression(plainSelect.getWhere(), scopeCondition));
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
- log.warn("数据权限SQL改写失败, 使用原始SQL", e);
|
|
|
+ log.error("数据权限SQL改写失败,拒绝查询(fail-closed): {}", e.getMessage());
|
|
|
+ throw new RuntimeException("数据权限拦截失败,查询被拒绝", e);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private Expression buildScopeCondition(Integer dataScope, LoginUser user) {
|
|
|
+ return switch (dataScope) {
|
|
|
+ case 1 -> // 仅本人
|
|
|
+ new EqualsTo(new Column("created_id"), new LongValue(user.getUserId()));
|
|
|
+ case 2 -> // 本部门
|
|
|
+ new EqualsTo(new Column("dept_id"), new LongValue(user.getDeptId()));
|
|
|
+ case 3 -> { // 本部门及以下
|
|
|
+ List<Long> deptIds = deptService.getDeptAndChildrenIds(user.getDeptId());
|
|
|
+ if (deptIds.isEmpty()) {
|
|
|
+ yield new EqualsTo(new Column("dept_id"), new LongValue(user.getDeptId()));
|
|
|
+ }
|
|
|
+ java.util.List<Expression> expressions = deptIds.stream()
|
|
|
+ .<Expression>map(LongValue::new).toList();
|
|
|
+ yield new InExpression(
|
|
|
+ new Column("dept_id"),
|
|
|
+ new ExpressionList(expressions));
|
|
|
+ }
|
|
|
+ default -> null;
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
private String extractTableName(PlainSelect plainSelect) {
|
|
|
if (plainSelect.getFromItem() == null) return null;
|
|
|
- return plainSelect.getFromItem().toString().replaceAll("[`\"]", "");
|
|
|
+ String table = plainSelect.getFromItem().toString();
|
|
|
+ // 去除别名,仅保留表名部分
|
|
|
+ int spaceIdx = table.indexOf(' ');
|
|
|
+ if (spaceIdx > 0) table = table.substring(0, spaceIdx);
|
|
|
+ return table.replaceAll("[`\"]", "");
|
|
|
}
|
|
|
}
|