diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln
index 0bf68ce8a..e8de430b4 100644
--- a/aspnet-core/LINGYUN.MicroService.All.sln
+++ b/aspnet-core/LINGYUN.MicroService.All.sln
@@ -849,6 +849,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Exporter.Pdf.Sp
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.Account.Security", "modules\account\LINGYUN.Abp.Account.Security\LINGYUN.Abp.Account.Security.csproj", "{5FA85E8E-3276-43DF-CC93-6A9847905166}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.AspNetCore.MultiTenancy", "framework\tenants\LINGYUN.Abp.AspNetCore.MultiTenancy\LINGYUN.Abp.AspNetCore.MultiTenancy.csproj", "{AEEA81D6-B282-93CF-862B-9FCF1A5052F7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -2203,6 +2205,10 @@ Global
{5FA85E8E-3276-43DF-CC93-6A9847905166}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5FA85E8E-3276-43DF-CC93-6A9847905166}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5FA85E8E-3276-43DF-CC93-6A9847905166}.Release|Any CPU.Build.0 = Release|Any CPU
+ {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {AEEA81D6-B282-93CF-862B-9FCF1A5052F7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -2615,6 +2621,7 @@ Global
{738A72FB-ED83-4127-AA3B-59BF90635F8F} = {A4633711-7FB6-411A-8D08-BB9A0A778046}
{9950639D-AA4C-4FF1-A65E-9790EB561C8A} = {A4633711-7FB6-411A-8D08-BB9A0A778046}
{5FA85E8E-3276-43DF-CC93-6A9847905166} = {9E72FEB9-A626-4312-892B-CDD043879758}
+ {AEEA81D6-B282-93CF-862B-9FCF1A5052F7} = {A5543E56-DA53-494D-A531-DA75091D46FF}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/FodyWeavers.xml b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/FodyWeavers.xml
new file mode 100644
index 000000000..5d6962159
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/FodyWeavers.xml
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/FodyWeavers.xsd b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/FodyWeavers.xsd
new file mode 100644
index 000000000..3f3946e28
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/FodyWeavers.xsd
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.
+
+
+
+
+ A comma-separated list of error codes that can be safely ignored in assembly verification.
+
+
+
+
+ 'false' to turn off automatic generation of the XML Schema file.
+
+
+
+
+
\ No newline at end of file
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN.Abp.AspNetCore.MultiTenancy.csproj b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN.Abp.AspNetCore.MultiTenancy.csproj
new file mode 100644
index 000000000..89b162615
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN.Abp.AspNetCore.MultiTenancy.csproj
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ net9.0
+ LINGYUN.Abp.AspNetCore.MultiTenancy
+ LINGYUN.Abp.AspNetCore.MultiTenancy
+ false
+ false
+ false
+ Library
+ enable
+
+
+
+
+
+
+
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs
new file mode 100644
index 000000000..61668fc97
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyModule.cs
@@ -0,0 +1,10 @@
+using Volo.Abp.Modularity;
+using VoloAbpAspNetCoreMultiTenancyModule = Volo.Abp.AspNetCore.MultiTenancy.AbpAspNetCoreMultiTenancyModule;
+
+namespace LINGYUN.Abp.AspNetCore.MultiTenancy;
+
+[DependsOn(typeof(VoloAbpAspNetCoreMultiTenancyModule))]
+public class AbpAspNetCoreMultiTenancyModule : AbpModule
+{
+
+}
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyResolveOptions.cs b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyResolveOptions.cs
new file mode 100644
index 000000000..1b7d0abc8
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpAspNetCoreMultiTenancyResolveOptions.cs
@@ -0,0 +1,13 @@
+namespace LINGYUN.Abp.AspNetCore.MultiTenancy;
+
+public class AbpAspNetCoreMultiTenancyResolveOptions
+{
+ ///
+ /// 仅解析域名中的租户, 默认: true
+ ///
+ public bool OnlyResolveDomain { get; set; }
+ public AbpAspNetCoreMultiTenancyResolveOptions()
+ {
+ OnlyResolveDomain = true;
+ }
+}
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs
new file mode 100644
index 000000000..d78531af5
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/AbpMultiTenancyOptionsExtensions.cs
@@ -0,0 +1,15 @@
+using System.Collections.Generic;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.AspNetCore.MultiTenancy;
+
+public static class AbpMultiTenancyOptionsExtensions
+{
+ public static void AddOnlyDomainTenantResolver(this AbpTenantResolveOptions options, string domainFormat)
+ {
+ options.TenantResolvers.InsertAfter(
+ r => r is CurrentUserTenantResolveContributor,
+ new OnlyDomainTenantResolveContributor(domainFormat)
+ );
+ }
+}
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/OnlyDomainTenantResolveContributor.cs b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/OnlyDomainTenantResolveContributor.cs
new file mode 100644
index 000000000..b272971ff
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/LINGYUN/Abp/AspNetCore/MultiTenancy/OnlyDomainTenantResolveContributor.cs
@@ -0,0 +1,52 @@
+using Microsoft.AspNetCore.Http;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Options;
+using System;
+using System.Net;
+using System.Threading.Tasks;
+using Volo.Abp.AspNetCore.MultiTenancy;
+using Volo.Abp.MultiTenancy;
+using Volo.Abp.Text.Formatting;
+
+namespace LINGYUN.Abp.AspNetCore.MultiTenancy;
+
+public class OnlyDomainTenantResolveContributor : HttpTenantResolveContributorBase
+{
+ public const string ContributorName = "Domain";
+
+ public override string Name => ContributorName;
+
+ private static readonly string[] ProtocolPrefixes = { "http://", "https://" };
+
+ private readonly string _domainFormat;
+
+ public OnlyDomainTenantResolveContributor(string domainFormat)
+ {
+ _domainFormat = domainFormat.RemovePreFix(ProtocolPrefixes);
+ }
+
+ protected override Task GetTenantIdOrNameFromHttpContextOrNullAsync(ITenantResolveContext context, HttpContext httpContext)
+ {
+ if (!httpContext.Request.Host.HasValue)
+ {
+ return Task.FromResult(null);
+ }
+
+ var options = httpContext.RequestServices.GetRequiredService>();
+ if (options.Value.OnlyResolveDomain)
+ {
+ // 仅仅解析域名, 如果请求的是IP地址, 则不使用这个解析贡献者
+ if (IPAddress.TryParse(httpContext.Request.Host.Host, out var _))
+ {
+ return Task.FromResult(null);
+ }
+ }
+
+ var hostName = httpContext.Request.Host.Value.RemovePreFix(ProtocolPrefixes);
+ var extractResult = FormattedStringValueExtracter.Extract(hostName, _domainFormat, ignoreCase: true);
+
+ context.Handled = true;
+
+ return Task.FromResult(extractResult.IsMatch ? extractResult.Matches[0].Value : null);
+ }
+}
diff --git a/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json
new file mode 100644
index 000000000..8ac6471cc
--- /dev/null
+++ b/aspnet-core/framework/tenants/LINGYUN.Abp.AspNetCore.MultiTenancy/Properties/launchSettings.json
@@ -0,0 +1,12 @@
+{
+ "profiles": {
+ "LINGYUN.Abp.AspNetCore.MultiTenancy": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "applicationUrl": "https://localhost:61811;http://localhost:61812"
+ }
+ }
+}
\ No newline at end of file
diff --git a/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.Configure.cs b/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.Configure.cs
index c9c9c2e7e..0080c2059 100644
--- a/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.Configure.cs
+++ b/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.Configure.cs
@@ -1,4 +1,5 @@
using DotNetCore.CAP;
+using LINGYUN.Abp.AspNetCore.MultiTenancy;
using LINGYUN.Abp.BlobStoring.OssManagement;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.LocalizationManagement;
@@ -14,7 +15,6 @@ using LINGYUN.Abp.Wrapper;
using LY.MicroService.AuthServer.Ui.Branding;
using Medallion.Threading;
using Medallion.Threading.Redis;
-using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Cors;
@@ -446,7 +446,7 @@ public partial class AuthServerModule
var domains = tenantResolveCfg.Get();
foreach (var domain in domains)
{
- options.AddDomainTenantResolver(domain);
+ options.AddOnlyDomainTenantResolver(domain);
}
});
}
diff --git a/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.cs b/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.cs
index f79f1b147..a4c7d5cd5 100644
--- a/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.cs
+++ b/aspnet-core/services/LY.MicroService.AuthServer/AuthServerModule.cs
@@ -2,6 +2,7 @@
using LINGYUN.Abp.Account.Web.OAuth;
using LINGYUN.Abp.Account.Web.OpenIddict;
using LINGYUN.Abp.AspNetCore.HttpOverrides;
+using LINGYUN.Abp.AspNetCore.MultiTenancy;
using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
using LINGYUN.Abp.AuditLogging.Elasticsearch;
using LINGYUN.Abp.BlobStoring.OssManagement;
@@ -69,6 +70,7 @@ namespace LY.MicroService.AuthServer;
typeof(AbpDataDbMigratorModule),
typeof(AbpAuditLoggingElasticsearchModule), // 放在 AbpIdentity 模块之后,避免被覆盖
typeof(AbpLocalizationCultureMapModule),
+ typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpAspNetCoreMvcWrapperModule),
typeof(AbpAspNetCoreHttpOverridesModule),
typeof(AbpTelemetrySkyWalkingModule),
diff --git a/aspnet-core/services/LY.MicroService.AuthServer/LY.MicroService.AuthServer.csproj b/aspnet-core/services/LY.MicroService.AuthServer/LY.MicroService.AuthServer.csproj
index 6c80ea30c..d1fed8872 100644
--- a/aspnet-core/services/LY.MicroService.AuthServer/LY.MicroService.AuthServer.csproj
+++ b/aspnet-core/services/LY.MicroService.AuthServer/LY.MicroService.AuthServer.csproj
@@ -54,6 +54,7 @@
+
diff --git a/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.Configure.cs b/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.Configure.cs
index b9a4dc9a0..66a6ef394 100644
--- a/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.Configure.cs
+++ b/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.Configure.cs
@@ -1,6 +1,7 @@
using DotNetCore.CAP;
using LINGYUN.Abp.Account.Web;
using LINGYUN.Abp.Account.Web.IdentityServer;
+using LINGYUN.Abp.AspNetCore.MultiTenancy;
using LINGYUN.Abp.IdentityServer.IdentityResources;
using LINGYUN.Abp.Localization.CultureMap;
using LINGYUN.Abp.LocalizationManagement;
@@ -372,7 +373,7 @@ public partial class IdentityServerModule
var domains = tenantResolveCfg.Get();
foreach (var domain in domains)
{
- options.AddDomainTenantResolver(domain);
+ options.AddOnlyDomainTenantResolver(domain);
}
});
}
diff --git a/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.cs b/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.cs
index 7bad8a130..0801af9d5 100644
--- a/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.cs
+++ b/aspnet-core/services/LY.MicroService.IdentityServer/IdentityServerModule.cs
@@ -1,6 +1,7 @@
using LINGYUN.Abp.Account;
using LINGYUN.Abp.Account.Web.IdentityServer;
using LINGYUN.Abp.AspNetCore.HttpOverrides;
+using LINGYUN.Abp.AspNetCore.MultiTenancy;
using LINGYUN.Abp.AspNetCore.Mvc.Wrapper;
using LINGYUN.Abp.AuditLogging.Elasticsearch;
using LINGYUN.Abp.Authentication.QQ;
@@ -68,6 +69,7 @@ namespace LY.MicroService.IdentityServer;
typeof(AbpDataDbMigratorModule),
typeof(AbpAuditLoggingElasticsearchModule), // 放在 AbpIdentity 模块之后,避免被覆盖
typeof(AbpLocalizationCultureMapModule),
+ typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpAspNetCoreMvcWrapperModule),
typeof(AbpAspNetCoreHttpOverridesModule),
typeof(AbpTelemetrySkyWalkingModule),
diff --git a/aspnet-core/services/LY.MicroService.IdentityServer/LY.MicroService.IdentityServer.csproj b/aspnet-core/services/LY.MicroService.IdentityServer/LY.MicroService.IdentityServer.csproj
index 4076974cd..fba73edd9 100644
--- a/aspnet-core/services/LY.MicroService.IdentityServer/LY.MicroService.IdentityServer.csproj
+++ b/aspnet-core/services/LY.MicroService.IdentityServer/LY.MicroService.IdentityServer.csproj
@@ -56,6 +56,7 @@
+