ASP.NET Core 5.0实现动态子域名路由绑定的方案咨询
.NET Core 5.0 动态子域名绑定实现方案
1. 前置泛域名配置
首先完成基础网络层配置,确保所有子域名请求能到达你的应用:
- 域名DNS后台添加
*.india.com的A/AAAA记录,解析到你的服务器或反向代理节点的公网IP - 如果你用了Nginx/IIS等反向代理,添加泛域名站点配置,将所有
*.india.com的请求统一转发到你的.NET Core 5.0应用监听的端口
2. 自定义子域名解析中间件
在ASP.NET Core请求管道中新增自定义中间件,负责提取子域名、匹配数据库规则:
2.1 编写中间件类
新建SubdomainMiddleware.cs文件,代码示例:
public class SubdomainMiddleware { private readonly RequestDelegate _next; public SubdomainMiddleware(RequestDelegate next) { _next = next; } public async Task InvokeAsync(HttpContext context, IConfiguration configuration, YourDbContext dbContext, IDistributedCache cache) { var host = context.Request.Host.Host.ToLower(); var mainDomain = configuration.GetValue<string>("MainDomain", "india.com"); // 排除主域名、www域名的请求 if (host.Equals(mainDomain, StringComparison.OrdinalIgnoreCase) || host.Equals($"www.{mainDomain}", StringComparison.OrdinalIgnoreCase)) { await _next(context); return; } // 提取子域名前缀 var subdomain = host.Replace($".{mainDomain}", "").Trim(); if (string.IsNullOrEmpty(subdomain)) { await _next(context); return; } // 优先读缓存,避免频繁查库 var cacheKey = $"subdomain_binding_{subdomain}"; var bindingConfig = await cache.GetStringAsync(cacheKey); SubdomainBinding binding = null; if (string.IsNullOrEmpty(bindingConfig)) { // 查数据库匹配规则 binding = await dbContext.SubdomainBindings .FirstOrDefaultAsync(s => s.Subdomain == subdomain && s.IsEnabled); if (binding != null) { // 缓存1小时,修改规则时主动删除对应缓存即可 await cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(binding), new DistributedCacheEntryOptions { AbsoluteExpirationRelativeToNow = TimeSpan.FromHours(1) }); } } else { binding = JsonSerializer.Deserialize<SubdomainBinding>(bindingConfig); } // 将匹配到的规则存入HttpContext,后续控制器/服务均可读取 context.Items["SubdomainBinding"] = binding; context.Items["CurrentSubdomain"] = subdomain; // 未匹配到规则的处理逻辑,可自定义为跳转404/主站 if (binding == null) { context.Response.Redirect($"https://{mainDomain}"); return; } await _next(context); } }
2.2 注册中间件
在Startup.cs的Configure方法中,路由中间件注册之前添加该中间件:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 其他前置中间件(异常处理、静态文件等)写在前面 // 注册子域名解析中间件 app.UseMiddleware<SubdomainMiddleware>(); app.UseRouting(); // 其他中间件(认证、授权、端点映射等) }
3. 数据库绑定规则表设计
示例EF Core实体类如下,你可以根据自身业务需求扩展字段:
public class SubdomainBinding { public int Id { get; set; } /// <summary> /// 子域名前缀,比如br、sa、rs等 /// </summary> public string Subdomain { get; set; } /// <summary> /// 绑定的业务类型,比如Tenant(租户)、SpecialPage(专题页)等 /// </summary> public string TargetType { get; set; } /// <summary> /// 绑定的业务资源ID /// </summary> public int TargetId { get; set; } public bool IsEnabled { get; set; } public DateTime CreateTime { get; set; } // 其他自定义字段,比如跳转地址、自定义配置等 }
你可以做一个后台管理页面,直接操作这张表即可实现子域名规则的动态新增、修改、停用,不需要修改任何配置或重启应用。
4. 业务逻辑对接
在控制器或业务服务中直接读取之前存入HttpContext的规则即可:
public class HomeController : Controller { public IActionResult Index() { var currentBinding = HttpContext.Items["SubdomainBinding"] as SubdomainBinding; var subdomain = HttpContext.Items["CurrentSubdomain"] as string; // 根据绑定规则执行对应业务逻辑: // 比如是租户类型,就根据TargetId加载对应租户的站点数据 // 比如是专题页类型,就跳转到对应专题页的Action返回内容 return View(); } }
注意事项
- 建议新增子域名合法性校验逻辑,避免特殊字符、违规子域名的请求
- 修改规则后记得删除对应缓存,确保规则即时生效
- 可以根据业务需要配置子域名的默认跳转、404逻辑
内容的提问来源于stack exchange,提问作者Yash Gajjar
相关产品推荐
相关产品推荐

