.NET 5 多域名路由配置及跨域访问限制问题求助(适配Azure Front Door)
Hey David, let's tackle your domain routing and access control needs step by step. Since you're deployed behind Azure Front Door, the key first step is ensuring your app correctly reads the X-Forwarded-Host header (you mentioned you have this logic, but we'll formalize it to avoid gaps), then building a custom attribute-based solution that ties domain validation to routing.
1. Ensure Correct Forwarded Host Configuration
First, confirm your app is properly configured to trust the X-Forwarded-Host header from Azure Front Door. Add this to your Startup.cs (or Program.cs if using top-level statements):
using Microsoft.AspNetCore.HttpOverrides; public void ConfigureServices(IServiceCollection services) { services.Configure<ForwardedHeadersOptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedHost | ForwardedHeaders.XForwardedProto; // Trust Azure Front Door's IP ranges (add all relevant ranges for your region) options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("13.107.6.152"), 24)); options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("13.107.18.16"), 22)); options.KnownNetworks.Add(new IPNetwork(IPAddress.Parse("13.107.24.0"), 22)); }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // Critical: Add this middleware BEFORE routing and authorization app.UseForwardedHeaders(); // Rest of your middleware pipeline (UseRouting, UseAuthorization, etc.) }
This ensures your app uses the actual client-facing domain from X-Forwarded-Host instead of Azure Front Door's internal hostname.
2. Custom Domain Route Attribute with Access Restriction
Since the built-in [Host] attribute might not work as expected with forwarded headers (or doesn't enforce strict access control), let's build a custom attribute that combines routing and domain validation.
Step 2.1: Create a Domain Validation Action Constraint
This constraint checks if the request's host matches the allowed domains specified in the attribute:
using Microsoft.AspNetCore.Mvc.ActionConstraints; public class DomainMatchConstraint : IActionConstraint { private readonly string[] _allowedDomains; public DomainMatchConstraint(string[] allowedDomains) { _allowedDomains = allowedDomains.Select(d => d.ToLowerInvariant()).ToArray(); } public int Order => 0; public bool Accept(ActionConstraintContext context) { // Get the forwarded host (fallback to request host if header is missing) var requestHost = context.HttpContext.Request.Headers["X-Forwarded-Host"].FirstOrDefault() ?? context.HttpContext.Request.Host.Host; requestHost = requestHost.ToLowerInvariant(); return _allowedDomains.Contains(requestHost); } }
Step 2.2: Create a Custom Domain Route Attribute
This attribute inherits from [Route] and adds the domain constraint:
using Microsoft.AspNetCore.Mvc; [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)] public class DomainRouteAttribute : RouteAttribute, IActionConstraintFactory { private readonly string[] _allowedDomains; public DomainRouteAttribute(string template, params string[] allowedDomains) : base(template) { _allowedDomains = allowedDomains; } public IActionConstraint CreateInstance(IServiceProvider services) { return new DomainMatchConstraint(_allowedDomains); } public bool IsReusable => true; }
3. Implement Routing & Access Restriction in Controllers
Now use this custom attribute to define your routes and enforce domain-specific access:
public class AboutUsController : Controller { // Only accessible via www.domaina.com/aboutus [DomainRoute("aboutus", "www.domaina.com")] public IActionResult AboutUsDomainA() { return View("AboutUs_DomainA"); } // Only accessible via www.domainb.com/aboutus [DomainRoute("aboutus", "www.domainb.com")] public IActionResult AboutUsDomainB() { return View("AboutUs_DomainB"); } } public class RestrictedPagesController : Controller { // Only accessible via www.domaina.com/pageA [DomainRoute("pageA", "www.domaina.com")] public IActionResult PageA_DomainA() { return View("PageA"); } // Only accessible via www.domainb.com/pageA [DomainRoute("pageA", "www.domainb.com")] public IActionResult PageA_DomainB() { return View("PageA_DomainB"); // Or reuse the same view with domain-specific logic } }
4. Handle Fallback for Unauthorized Domain Access
If you want to return a custom error when a user tries to access a route from an invalid domain, add a catch-all route with lower priority:
[Route("{*path}")] public IActionResult DomainNotFound() { return NotFound("This page is not available on this domain."); }
Why Your Previous Attempts Might Have Failed
- The built-in
[Host]attribute relies on theRequest.Hostproperty, which won't reflect the client domain unlessForwardedHeadersMiddlewareis properly configured and ordered before routing. - The ASP.NET Core 2.0 domain routing methods don't natively account for forwarded headers, and their implementation can conflict with .NET 5's updated routing system.
This custom solution gives you full control over allowed domains, works seamlessly with forwarded headers, and integrates perfectly with your existing attribute routing pattern.
内容的提问来源于stack exchange,提问作者David Hendrick

