# 用户忽略租户隔离查询功能实现 ## 🔍 问题背景 在`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 ``` **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] 创建测试用例验证功能 ## 🎉 总结 用户忽略租户隔离查询功能已完整实现,具备以下特性: - **跨租户能力**: 忽略租户隔离,可查询任意租户用户 - **数据完整性**: 返回完整的用户信息和关联数据 - **安全可控**: 仅在特定业务场景使用,不暴露给前端 - **性能优化**: 单次查询获取完整信息 现在在支付回调等跨租户业务场景中,可以正确查询到用户信息,不会因为租户隔离导致查询失败。