MoneyTree.MultiTenancy 1.0.4

MoneyTree.MultiTenancy 多租户

📋 概述

MoneyTree.MultiTenancy 提供可插拔的多租户中间件,支持从多种来源(HTTP 头、子域名、JWT Claim)自动解析租户标识,并提供租户上下文管理、租户信息存储和组合策略。结合 MoneyTree.EFCore.MultiTenancy 扩展包可实现数据库级别的自动租户数据隔离。

属性 说明
NuGet 包 MoneyTree.MultiTenancy
外部依赖 MoneyTree.Core
定位 可插拔的多租户中间件

🏗️ 项目文件结构

MoneyTree.MultiTenancy/
├── MoneyTree.MultiTenancy.csproj
├── GlobalUsings.cs
├── TenantInfo.cs                          # 租户信息模型
├── Abstractions/
│   ├── IMultiTenant.cs                    # 多租户实体标记接口
│   ├── ITenantContext.cs                  # 租户上下文接口
│   ├── ITenantContextAccessor.cs          # 租户上下文访问器
│   ├── ITenantResolutionStrategy.cs       # 租户解析策略接口
│   └── ITenantStore.cs                    # 租户信息存储接口
├── Core/
│   ├── MultiTenantEntity.cs               # 多租户实体/聚合根基类
│   ├── TenantContext.cs                   # 租户上下文默认实现
│   └── TenantContextAccessor.cs           # 租户上下文访问器实现
├── Resolution/
│   ├── HeaderResolutionStrategy.cs        # HTTP 头解析策略
│   ├── HostResolutionStrategy.cs          # 子域名解析策略
│   ├── ClaimResolutionStrategy.cs         # JWT Claim 解析策略
│   ├── DefaultTenantResolutionStrategy.cs  # 默认租户策略(兜底)
│   └── CompositeResolutionStrategy.cs     # 组合策略(多策略链式尝试)
├── Store/
│   └── InMemoryTenantStore.cs             # 内存租户信息存储
├── Middleware/
│   └── MultiTenancyMiddleware.cs          # 多租户 HTTP 中间件
└── Extensions/
    ├── MultiTenancyBuilder.cs             # 流畅配置构造器
    └── MultiTenancyExtensions.cs          # DI 注册扩展

🎯 核心能力

能力 说明
租户解析 自动从请求中提取租户标识
上下文管理 Scoped 生命周期的 TenantContext,随请求自动创建和清理
实体标记 IMultiTenant 接口标记需要租户隔离的实体
策略组合 多策略组合,按优先级依次尝试解析
租户验证 检出过期/停用的租户并拒绝请求
灵活存储 内置 InMemoryTenantStore,可通过 ITenantStore 扩展

🚀 快速开始

基础配置

// Program.cs
using MoneyTree.MultiTenancy.Extensions;

var builder = WebApplication.CreateBuilder(args);

// 最简配置:Header 策略 + 内存存储 + 默认租户
builder.Services.AddMoneyTreeMultiTenancy();

var app = builder.Build();
app.UseMoneyTreeMultiTenancy();
app.Run();

自定义配置

builder.Services.AddMoneyTreeMultiTenancy(mt =>
{
    mt.UseHeader("X-Tenant-Id")           // 从请求头解析
      .UseHost()                          // 从子域名解析
      .UseClaim("tenant_id")              // 从 JWT Claim 解析
      .UseDefault("default-tenant")       // 解析失败时的默认租户
      .UseInMemoryStore(store =>          // 内存存储
          store.Seed(new TenantInfo
          {
              Id = "tenant-001",
              Name = "企业客户A",
              ExpiresAt = DateTime.UtcNow.AddYears(1)
          }));
});

📖 使用示例

租户解析策略

策略 NuGet 方法 示例 说明
Header UseHeader("X-Tenant-Id") X-Tenant-Id: tenant-001 从 HTTP 请求头解析
Host UseHost() tenant-001.example.com 从子域名解析
Claim UseClaim("tenant_id") JWT tenant_id claim 从 Token 中解析
Default UseDefault("default") 所有策略失败后兜底 兜底默认租户

标记多租户实体

// 方式一:实现 IMultiTenant 接口
public class Order : AggregateRoot, IMultiTenant
{
    public string? TenantId { get; set; }
    public string OrderNumber { get; set; } = string.Empty;
}

// 方式二:继承 MultiTenantEntity 基类
public class Product : MultiTenantEntity
{
    public string Name { get; set; } = string.Empty;
}

在服务中使用租户上下文

public class OrderService 
{
    [Inject] public ITenantContextAccessor TenantAccessor { get; private set; } = default!;

    public async Task<List<Order>> GetOrdersAsync()
    {
        var tenantId = TenantAccessor.TenantContext?.TenantId;
        // 查询自动应用租户筛选(需配合 MoneyTree.EFCore.MultiTenancy)
        return await _db.Orders.ToListAsync();
    }
}

TenantInfo 模型

属性 类型 说明
Id string 租户唯一标识
Name string 租户名称
DisplayName string 租户显示名称
IsActive bool 是否活跃(非活跃租户的请求将被拒绝)
CreatedAt DateTime 租户创建时间
ExpiresAt DateTime? 租户过期时间
Properties Dictionary<string, string> 自定义属性(如连接字符串、存储配额)

🛡️ 中间件执行流程

HTTP 请求到达
    │
    ▼
MultiTenancyMiddleware
    │
    ├── 1. 通过 ITenantResolutionStrategy 解析 TenantId
    │        ├── Header → Host → Claim → Default(按策略链依次尝试)
    │
    ├── 2. 通过 ITenantStore 获取 TenantInfo
    │
    ├── 3. 验证租户状态
    │        ├── IsActive == false → 返回 403
    │        ├── IsExpired() == true → 返回 403
    │
    ├── 4. 创建 TenantContext(Scoped)
    │
    └── 5. 继续执行请求管道

🔗 与 EF Core 多租户联动

MoneyTree.EFCore.MultiTenancy 扩展包自动集成此模块,实现:

  • TenantFilterInterceptor:查询时自动添加 WHERE TenantId = @currentTenantId
  • TenantSaveChangesInterceptor:新增实体时自动填充 TenantId
  • IgnoreTenantFilter():管理后台跨租户查询

详见 MoneyTree.EFCore 文档

Showing the top 20 packages that depend on MoneyTree.MultiTenancy.

Packages Downloads
MoneyTree.Audit.Shared
MoneyTree Audit 共享层。提供审计实体模型、EF Core 配置和 EfAuditLogger 直写实现。业务服务引用此包后,可通过独立 DbContext 直写审计表,审计日志不受业务事务回滚影响。
2
MoneyTree.EFCore.MultiTenancy
MoneyTree Framework EF Core 多租户扩展包。提供租户筛选拦截器、租户自动填充拦截器。
2
MoneyTree.Audit.Shared
MoneyTree Audit 共享层。提供审计实体模型、EF Core 配置和 EfAuditLogger 直写实现。业务服务引用此包后,可通过 DbContext 在同事务中直接写入审计表,零网络调用、强一致、实时。
1
MoneyTree.EFCore.MultiTenancy
MoneyTree Framework EF Core 多租户扩展包。提供租户筛选拦截器、租户自动填充拦截器。
1

Version Downloads Last updated
1.0.5 1 7/21/2026
1.0.4 1 7/12/2026