# 部门数据隔离拦截器

## 概述

`DepartmentDataInterceptor` 是一个 MyBatis 拦截器，用于自动为涉及部门隔离的数据库操作添加部门过滤条件，确保用户只能访问属于自己部门的数据。

## 功能特性

1. **自动部门过滤**: 自动为 SELECT、UPDATE、DELETE 操作添加部门过滤条件
2. **超级管理员支持**: 超级管理员可以访问所有部门的数据，不受隔离限制
3. **超级管理员操作日志**: 自动记录超级管理员的跨部门数据访问操作到系统操作日志
4. **配置化管理**: 支持通过配置文件启用/禁用功能和调试日志
5. **SQL 安全**: 内置 SQL 注入防护机制
6. **透明集成**: 对现有业务代码无侵入性

## 目标表

拦截器会对以下表进行部门隔离：

- `dc_contract` - 合同管理表
- `dc_service_period` - 服务周期管理表  
- `dc_employee_info` - 员工信息表
- `dc_employee_library` - 员工库表
- `dc_credit` - 债权管理表
- `dc_bank_institution` - 银行机构表

## 工作原理

### 1. 拦截点

拦截器在以下两个层面进行拦截：

- **Executor 层面**: 拦截 `query` 和 `update` 方法，为参数添加部门过滤条件
- **StatementHandler 层面**: 拦截 `prepare` 方法，直接修改 SQL 语句添加 WHERE 条件

### 2. 过滤逻辑

1. 检查功能是否启用（通过配置）
2. 检查当前用户是否为超级管理员
   - 如果是超级管理员，记录操作日志并跳过部门隔离
   - 如果不是，继续执行部门过滤逻辑
3. 获取当前用户的部门ID
4. 检查SQL是否涉及目标表
5. 添加部门过滤条件

### 3. SQL 修改示例

**原始 SQL:**
```sql
SELECT * FROM dc_contract WHERE contract_status = 'ACTIVE'
```

**修改后 SQL:**
```sql
SELECT * FROM dc_contract WHERE dc_contract.dept_id = 100 AND contract_status = 'ACTIVE'
```

## 配置选项

在 `application.yml` 中配置：

```yaml
department:
  isolation:
    enabled: true          # 是否启用部门数据隔离功能
    sql-logging: false     # 是否启用SQL日志记录
    super-admin-role: admin # 超级管理员角色标识
```

## 使用方式

### 1. 自动注册

拦截器通过 `MyBatisConfig` 自动注册到 MyBatis 中，无需手动配置。

### 2. 部门上下文

拦截器依赖 `DepartmentContextHolder` 获取当前用户的部门信息：

```java
// 获取当前用户部门ID
Long deptId = DepartmentContextHolder.getCurrentDeptId();

// 检查是否为超级管理员
boolean isSuperAdmin = DepartmentContextHolder.isSuperAdmin();
```

### 3. 透明使用

对于业务代码，部门隔离是完全透明的：

```java
// 业务代码无需修改，拦截器会自动添加部门过滤
List<Contract> contracts = contractMapper.selectContractList(contract);
```

## 安全特性

1. **SQL 注入防护**: 内置正则表达式检测潜在的 SQL 注入攻击
2. **异常处理**: 拦截器异常不会影响业务流程的正常执行
3. **权限验证**: 严格的超级管理员权限验证机制

## 性能考虑

1. **索引优化**: 确保所有目标表的 `dept_id` 字段都有索引
2. **条件优化**: 部门条件会添加在 WHERE 子句的最前面，便于索引使用
3. **缓存友好**: 不影响 MyBatis 的缓存机制

## 注意事项

1. 确保所有目标表都已添加 `dept_id` 字段
2. 确保 `DepartmentContextHolder` 能正确获取用户部门信息
3. 超级管理员的跨部门数据访问操作会被自动记录到系统操作日志表 `sys_oper_log` 中
4. 建议在生产环境中关闭 SQL 日志记录以提高性能
5. 超级管理员操作日志记录失败不会影响业务操作的正常执行

## 故障排除

### 1. 拦截器不生效

- 检查配置 `department.isolation.enabled` 是否为 `true`
- 检查目标表名是否在 `TARGET_TABLES` 集合中
- 检查 MyBatis 配置是否正确注册了拦截器

### 2. 无法获取部门ID

- 检查用户是否已登录
- 检查 `SecurityUtils` 是否能正确获取用户信息
- 检查用户的部门信息是否完整

### 3. SQL 修改异常

- 检查 SQL 语法是否正确
- 检查是否存在复杂的子查询或联表查询
- 启用 SQL 日志记录查看修改后的 SQL