diff --git a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs
index b657b92..4001b0a 100644
--- a/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs
+++ b/src/Application/TakeoutSaaS.Application/Dictionary/Services/DictionaryAppService.cs
@@ -327,7 +327,7 @@ public sealed class DictionaryAppService(
var tenantId = tenantProvider.GetCurrentTenantId();
if (scope == DictionaryScope.System)
{
- EnsurePlatformTenant(tenantId);
+ EnsureSystemTenant(tenantId);
return 0;
}
@@ -362,9 +362,9 @@ public sealed class DictionaryAppService(
}
}
- private void EnsurePlatformTenant(long tenantId)
+ private void EnsureSystemTenant(long tenantId)
{
- // 1. (空行后) 系统字典只能在平台租户(TenantId=0)上下文中操作
+ // 1. (空行后) 系统字典只能在系统租户(TenantId=0)上下文中操作
if (tenantId != 0)
{
throw new BusinessException(ErrorCodes.Forbidden, "租户端不允许操作系统字典");
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs
index d689c2b..caee976 100644
--- a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs
@@ -5,7 +5,7 @@ using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Tenants.Entities;
///
-/// 平台租户信息,描述租户的生命周期与基础资料。
+/// 租户信息,描述租户的生命周期与基础资料。
///
public sealed class Tenant : AuditableEntityBase
{
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs
index 4bc9089..be264e3 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Persistence/AppDataSeeder.cs
@@ -39,7 +39,7 @@ public sealed class AppDataSeeder(
var appDbContext = scope.ServiceProvider.GetRequiredService();
var dictionaryDbContext = scope.ServiceProvider.GetRequiredService();
- await EnsurePlatformTenantAsync(appDbContext, cancellationToken);
+ await EnsureSystemTenantAsync(appDbContext, cancellationToken);
var defaultTenantId = await EnsureDefaultTenantAsync(appDbContext, cancellationToken);
await EnsureDictionarySeedsAsync(dictionaryDbContext, defaultTenantId, cancellationToken);
@@ -132,9 +132,9 @@ public sealed class AppDataSeeder(
}
///
- /// 确保平台租户存在。
+ /// 确保系统租户存在(TenantId=0,用于系统级数据归属)。
///
- private async Task EnsurePlatformTenantAsync(TakeoutAppDbContext dbContext, CancellationToken cancellationToken)
+ private async Task EnsureSystemTenantAsync(TakeoutAppDbContext dbContext, CancellationToken cancellationToken)
{
var existingTenant = await dbContext.Tenants
.IgnoreQueryFilters()
@@ -142,20 +142,47 @@ public sealed class AppDataSeeder(
if (existingTenant != null)
{
+ // 1. (空行后) 若历史数据仍为 PLATFORM,则自动修正为 SYSTEM
+ var updated = false;
+ if (!string.Equals(existingTenant.Code, "SYSTEM", StringComparison.Ordinal))
+ {
+ existingTenant.Code = "SYSTEM";
+ updated = true;
+ }
+
+ if (!string.Equals(existingTenant.Name, "System", StringComparison.Ordinal))
+ {
+ existingTenant.Name = "System";
+ updated = true;
+ }
+
+ if (existingTenant.Status != TenantStatus.Active)
+ {
+ existingTenant.Status = TenantStatus.Active;
+ updated = true;
+ }
+
+ if (updated)
+ {
+ dbContext.Tenants.Update(existingTenant);
+ await dbContext.SaveChangesAsync(cancellationToken);
+ logger.LogInformation("AppSeed 已更新系统租户 SYSTEM");
+ }
+
return;
}
var tenant = new Tenant
{
Id = 0,
- Code = "PLATFORM",
- Name = "Platform",
+ Code = "SYSTEM",
+ Name = "System",
Status = TenantStatus.Active
};
await dbContext.Tenants.AddAsync(tenant, cancellationToken);
await dbContext.SaveChangesAsync(cancellationToken);
- logger.LogInformation("AppSeed 已创建平台租户 PLATFORM");
+ logger.LogInformation("AppSeed 已创建系统租户 SYSTEM");
}
///
diff --git a/src/Modules/TakeoutSaaS.Module.Tenancy/TenantResolutionMiddleware.cs b/src/Modules/TakeoutSaaS.Module.Tenancy/TenantResolutionMiddleware.cs
index e686b7f..be230e0 100644
--- a/src/Modules/TakeoutSaaS.Module.Tenancy/TenantResolutionMiddleware.cs
+++ b/src/Modules/TakeoutSaaS.Module.Tenancy/TenantResolutionMiddleware.cs
@@ -89,18 +89,25 @@ public sealed class TenantResolutionMiddleware(
private static TenantContext ResolveTenant(HttpContext context, TenantResolutionOptions options)
{
var request = context.Request;
+ var isAuthenticated = context.User?.Identity?.IsAuthenticated == true;
// 1. Token Claim(已认证请求必须以 Claim 为准,避免 Header 覆盖导致跨租户访问)
var claim = context.User?.FindFirst("tenant_id");
- if (claim != null && long.TryParse(claim.Value, out var claimTenant))
+ if (claim != null && long.TryParse(claim.Value, out var claimTenant) && claimTenant > 0)
{
return new TenantContext(claimTenant, null, "claim:tenant_id");
}
+ // 1.1 (空行后) 已认证但缺少合法租户 Claim,则视为未解析(不允许 Header 覆盖)
+ if (isAuthenticated)
+ {
+ return TenantContext.Empty;
+ }
// 2. Header 中的租户 ID
if (!string.IsNullOrWhiteSpace(options.TenantIdHeaderName) &&
request.Headers.TryGetValue(options.TenantIdHeaderName, out var tenantHeader) &&
- long.TryParse(tenantHeader.FirstOrDefault(), out var headerTenantId))
+ long.TryParse(tenantHeader.FirstOrDefault(), out var headerTenantId) &&
+ headerTenantId > 0)
{
return new TenantContext(headerTenantId, null, $"header:{options.TenantIdHeaderName}");
}
@@ -120,7 +127,7 @@ public sealed class TenantResolutionMiddleware(
var host = request.Host.Host;
if (!string.IsNullOrWhiteSpace(host))
{
- if (options.DomainTenantMap.TryGetValue(host, out var tenantFromHost))
+ if (options.DomainTenantMap.TryGetValue(host, out var tenantFromHost) && tenantFromHost > 0)
{
return new TenantContext(tenantFromHost, null, $"host:{host}");
}
@@ -143,7 +150,7 @@ public sealed class TenantResolutionMiddleware(
return false;
}
- return options.CodeTenantMap.TryGetValue(code, out tenantId);
+ return options.CodeTenantMap.TryGetValue(code, out tenantId) && tenantId > 0;
}
private static string? ResolveCodeFromHost(string host, string? rootDomain)