小程序开发-服务端
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

6.5 KiB

用户忽略租户隔离查询功能实现

🔍 问题背景

ShopOrderUpdate10550ServiceImpl.java中,需要根据订单的用户ID查询用户信息:

final User user = userService.getById(order.getUserId());

但是由于租户隔离机制,可能无法查询到其他租户的用户信息,导致业务逻辑失败。

🎯 解决方案

实现了一个忽略租户隔离的用户查询方法getByIdIgnoreTenant,确保能够跨租户查询用户信息。

🔧 实现内容

1. UserService接口扩展

文件: src/main/java/com/gxwebsoft/common/system/service/UserService.java

/**
 * 根据用户ID查询用户(忽略租户隔离)
 * @param userId 用户ID
 * @return User
 */
User getByIdIgnoreTenant(Integer userId);

2. UserMapper数据库操作

文件: src/main/java/com/gxwebsoft/common/system/mapper/UserMapper.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

@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

<!-- 根据用户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

// 修改前(受租户隔离影响)
final User user = userService.getById(order.getUserId());

// 修改后(忽略租户隔离)
final User user = userService.getByIdIgnoreTenant(order.getUserId());

🔄 使用场景

1. 支付回调处理

// 在支付回调中需要查询订单用户信息
final User user = userService.getByIdIgnoreTenant(order.getUserId());
if (user != null) {
    // 处理用户相关业务逻辑
    log.info("用户信息 - ID: {}, 用户名: {}, 租户: {}", 
        user.getUserId(), user.getUsername(), user.getTenantId());
}

2. 跨租户业务处理

// 需要处理其他租户用户的业务
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. 跨租户查询测试 - 验证查询不同租户用户的能力

运行测试

# 运行单个测试类
mvn test -Dtest=UserIgnoreTenantTest

# 运行特定测试方法
mvn test -Dtest=UserIgnoreTenantTest#testGetByIdIgnoreTenant

📋 对比分析

方法 租户隔离 使用场景 安全性
getById() 受限制 普通业务查询
getByIdIgnoreTenant() 忽略 跨租户业务处理 中等

🔍 使用注意事项

1. 使用场景限制

  • 仅在确实需要跨租户查询时使用
  • 主要用于内部业务逻辑,不暴露给前端
  • 避免在普通的CRUD操作中使用

2. 安全考虑

  • 确保调用方有合理的业务需求
  • 记录关键操作日志
  • 避免敏感信息泄露

3. 性能考虑

  • 查询结果包含关联数据,注意性能影响
  • 在高并发场景下谨慎使用
  • 考虑添加缓存机制

📊 监控和日志

使用日志

log.info("跨租户查询用户 - 用户ID: {}, 查询结果: {}", 
    userId, user != null ? "成功" : "失败");

业务日志

if (user != null) {
    log.info("用户信息 - ID: {}, 用户名: {}, 租户ID: {}", 
        user.getUserId(), user.getUsername(), user.getTenantId());
}

验证清单

  • UserService接口添加getByIdIgnoreTenant方法
  • UserMapper添加selectByIdIgnoreTenant方法
  • 使用@InterceptorIgnore忽略租户隔离
  • UserServiceImpl实现业务逻辑
  • UserMapper.xml添加SQL映射
  • ShopOrderUpdate10550ServiceImpl使用新方法
  • 添加参数验证和空值处理
  • 创建测试用例验证功能

🎉 总结

用户忽略租户隔离查询功能已完整实现,具备以下特性:

  • 跨租户能力: 忽略租户隔离,可查询任意租户用户
  • 数据完整性: 返回完整的用户信息和关联数据
  • 安全可控: 仅在特定业务场景使用,不暴露给前端
  • 性能优化: 单次查询获取完整信息

现在在支付回调等跨租户业务场景中,可以正确查询到用户信息,不会因为租户隔离导致查询失败。