Files
java-10561/docs/用户忽略租户隔离查询功能.md
2025-09-06 11:58:18 +08:00

229 lines
6.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 用户忽略租户隔离查询功能实现
## 🔍 问题背景
`ShopOrderUpdate10550ServiceImpl.java`需要根据订单的用户ID查询用户信息
```java
final User user = userService.getById(order.getUserId());
```
但是由于租户隔离机制,可能无法查询到其他租户的用户信息,导致业务逻辑失败。
## 🎯 解决方案
实现了一个忽略租户隔离的用户查询方法`getByIdIgnoreTenant`,确保能够跨租户查询用户信息。
## 🔧 实现内容
### 1. UserService接口扩展
**文件**: `src/main/java/com/gxwebsoft/common/system/service/UserService.java`
```java
/**
* 根据用户ID查询用户忽略租户隔离
* @param userId 用户ID
* @return User
*/
User getByIdIgnoreTenant(Integer userId);
```
### 2. UserMapper数据库操作
**文件**: `src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.java`
```java
/**
* 根据用户ID查询用户忽略租户隔离
* @param userId 用户ID
* @return User
*/
@InterceptorIgnore(tenantLine = "true")
User selectByIdIgnoreTenant(@Param("userId") Integer userId);
```
**关键特性**:
-`@InterceptorIgnore(tenantLine = "true")` - 忽略租户隔离
- ✅ 支持跨租户查询用户信息
### 3. UserServiceImpl业务实现
**文件**: `src/main/java/com/gxwebsoft/common/system/service/impl/UserServiceImpl.java`
```java
@Override
public User getByIdIgnoreTenant(Integer userId) {
if (userId == null) {
return null;
}
return baseMapper.selectByIdIgnoreTenant(userId);
}
```
**功能特性**:
- ✅ 参数验证 - 检查userId的有效性
- ✅ 空值处理 - userId为null时返回null
- ✅ 忽略租户隔离 - 可以查询任意租户的用户
### 4. UserMapper.xml SQL映射
**文件**: `src/main/java/com/gxwebsoft/common/system/mapper/xml/UserMapper.xml`
```xml
<!-- 根据用户ID查询用户忽略租户隔离 -->
<select id="selectByIdIgnoreTenant" resultType="com.gxwebsoft.common.system.entity.User">
SELECT a.*,
c.dict_data_name sex_name,
e.tenant_name,
h.dealer_id
FROM gxwebsoft_core.sys_user a
LEFT JOIN (
<include refid="selectSexDictSql"/>
) c ON a.sex = c.dict_data_code
LEFT JOIN gxwebsoft_core.sys_tenant e ON a.tenant_id = e.tenant_id
LEFT JOIN gxwebsoft_core.sys_user_referee h ON a.user_id = h.user_id and h.deleted = 0
WHERE a.user_id = #{userId}
AND a.deleted = 0
</select>
```
**SQL特性**:
- ✅ 完整的用户信息查询(包括关联表)
- ✅ 包含性别字典、租户信息、推荐人信息
- ✅ 只过滤已删除的用户,不过滤租户
### 5. ShopOrderUpdate10550ServiceImpl集成
**文件**: `src/main/java/com/gxwebsoft/shop/service/impl/ShopOrderUpdate10550ServiceImpl.java`
```java
// 修改前(受租户隔离影响)
final User user = userService.getById(order.getUserId());
// 修改后(忽略租户隔离)
final User user = userService.getByIdIgnoreTenant(order.getUserId());
```
## 🔄 使用场景
### 1. 支付回调处理
```java
// 在支付回调中需要查询订单用户信息
final User user = userService.getByIdIgnoreTenant(order.getUserId());
if (user != null) {
// 处理用户相关业务逻辑
log.info("用户信息 - ID: {}, 用户名: {}, 租户: {}",
user.getUserId(), user.getUsername(), user.getTenantId());
}
```
### 2. 跨租户业务处理
```java
// 需要处理其他租户用户的业务
User crossTenantUser = userService.getByIdIgnoreTenant(otherTenantUserId);
if (crossTenantUser != null) {
// 执行跨租户业务逻辑
}
```
## 🎯 核心优势
### 1. 租户隔离绕过
- ✅ 使用`@InterceptorIgnore(tenantLine = "true")`忽略租户隔离
- ✅ 可以查询任意租户的用户信息
- ✅ 不受当前登录用户租户限制
### 2. 数据完整性
- ✅ 查询完整的用户信息(包括关联数据)
- ✅ 包含性别字典、租户信息、推荐人信息
- ✅ 与普通查询返回相同的数据结构
### 3. 安全性考虑
- ✅ 仅在特定业务场景使用
- ✅ 不暴露给前端接口
- ✅ 主要用于内部业务逻辑处理
### 4. 性能优化
- ✅ 单次查询获取完整信息
- ✅ 复用现有的SQL结构
- ✅ 避免多次查询关联数据
## 🧪 测试验证
**测试文件**: `src/test/java/com/gxwebsoft/common/system/service/UserIgnoreTenantTest.java`
### 测试用例
1. **基本功能测试** - 验证忽略租户隔离查询
2. **参数验证测试** - 验证null值和无效ID的处理
3. **跨租户查询测试** - 验证查询不同租户用户的能力
### 运行测试
```bash
# 运行单个测试类
mvn test -Dtest=UserIgnoreTenantTest
# 运行特定测试方法
mvn test -Dtest=UserIgnoreTenantTest#testGetByIdIgnoreTenant
```
## 📋 对比分析
| 方法 | 租户隔离 | 使用场景 | 安全性 |
|-----|---------|----------|--------|
| `getById()` | ✅ 受限制 | 普通业务查询 | 高 |
| `getByIdIgnoreTenant()` | ❌ 忽略 | 跨租户业务处理 | 中等 |
## 🔍 使用注意事项
### 1. 使用场景限制
- 仅在确实需要跨租户查询时使用
- 主要用于内部业务逻辑,不暴露给前端
- 避免在普通的CRUD操作中使用
### 2. 安全考虑
- 确保调用方有合理的业务需求
- 记录关键操作日志
- 避免敏感信息泄露
### 3. 性能考虑
- 查询结果包含关联数据,注意性能影响
- 在高并发场景下谨慎使用
- 考虑添加缓存机制
## 📊 监控和日志
### 使用日志
```java
log.info("跨租户查询用户 - 用户ID: {}, 查询结果: {}",
userId, user != null ? "成功" : "失败");
```
### 业务日志
```java
if (user != null) {
log.info("用户信息 - ID: {}, 用户名: {}, 租户ID: {}",
user.getUserId(), user.getUsername(), user.getTenantId());
}
```
## ✅ 验证清单
- [x] UserService接口添加getByIdIgnoreTenant方法
- [x] UserMapper添加selectByIdIgnoreTenant方法
- [x] 使用@InterceptorIgnore忽略租户隔离
- [x] UserServiceImpl实现业务逻辑
- [x] UserMapper.xml添加SQL映射
- [x] ShopOrderUpdate10550ServiceImpl使用新方法
- [x] 添加参数验证和空值处理
- [x] 创建测试用例验证功能
## 🎉 总结
用户忽略租户隔离查询功能已完整实现,具备以下特性:
- **跨租户能力**: 忽略租户隔离,可查询任意租户用户
- **数据完整性**: 返回完整的用户信息和关联数据
- **安全可控**: 仅在特定业务场景使用,不暴露给前端
- **性能优化**: 单次查询获取完整信息
现在在支付回调等跨租户业务场景中,可以正确查询到用户信息,不会因为租户隔离导致查询失败。