You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Startup.cs中根据URL路径/端点动态加载不同服务?

解决方案:ASP.NET Core 根据请求URL动态加载服务

首先要明确一个核心限制:ConfigureServices方法是应用启动阶段执行的,仅运行一次,此时没有任何请求上下文,无法获取当前访问的URL路径。你之前尝试用HttpContextAccessor失败,就是因为在启动阶段还不存在请求,自然拿不到路径信息。

要实现根据URL动态加载不同服务的需求,需要换一种思路:先注册所有可能用到的服务,再在请求处理阶段(中间件、过滤器等)根据路径启用对应的功能。以下是针对你场景的具体实现方案:

步骤1:注册所有基础服务

将两组服务都注册到容器中,同时添加HttpContextAccessor用于后续获取请求路径:

public void ConfigureServices(IServiceCollection services)
{
    services.AddOptions();
    // 注册HttpContextAccessor,用于后续获取请求路径
    services.AddHttpContextAccessor();

    var graphBaseUrl = Configuration["Graph:BaseUrl"]; //"https://graph.microsoft.com/v1.0";
    var userReadScope = "user.read";
    string[] initialScopes = new string[] { userReadScope };

    // 注册第二组服务(对应/Foo/路径)
    services.AddMvc()
        .AddSessionStateTempDataProvider();
    services.AddSession();

    // 注册第一组服务(对应/Foo/Bar/路径)
    services.AddMicrosoftIdentityWebAppAuthentication(Configuration, configSectionName: "ABC")
        .EnableTokenAcquisitionToCallDownstreamApi(initialScopes)
        .AddMicrosoftGraph(graphBaseUrl, userReadScope)
        .AddSessionTokenCaches();

    // 添加动态授权过滤器,替代硬编码的全局授权策略
    services.AddControllersWithViews(options =>
    {
        options.Filters.Add<DynamicAuthorizeFilter>();
    }).AddMicrosoftIdentityUI();

    services.AddRazorPages();
}

步骤2:实现动态授权过滤器

创建一个自定义过滤器,根据请求路径判断是否需要强制认证:

public class DynamicAuthorizeFilter : IAsyncAuthorizationFilter
{
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly AuthorizationPolicy _authenticatedPolicy;

    public DynamicAuthorizeFilter(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
        // 构建需要认证的策略
        _authenticatedPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
    }

    public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        var requestPath = _httpContextAccessor.HttpContext.Request.Path;
        // 当路径包含/Bar时,强制执行认证检查
        if (requestPath.StartsWithSegments("/Bar"))
        {
            var authorizeFilter = new AuthorizeFilter(_authenticatedPolicy);
            await authorizeFilter.OnAuthorizationAsync(context);
        }
        // 其他路径不做认证要求
    }
}

步骤3:配置统一的请求管道

在Configure方法中配置通用的管道,无需拆分端点(如果需要也可以用MapWhen做分支,这里提供简化版本):

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();
    app.UseSession();
    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllerRoute(
            name: "default",
            pattern: "{controller=Home}/{action=Site}/{id?}"
        );
        endpoints.MapControllerRoute(
            name: "Bar",
            pattern: "{controller=Bar}/{action=Index}/{id?}"
        );
        endpoints.MapRazorPages();
    });
}

可选优化:用MapWhen拆分请求管道

如果希望不同路径使用完全独立的中间件管道,可以用MapWhen做分支,进一步隔离两组服务的执行逻辑:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    app.UseHttpsRedirection();
    app.UseStaticFiles();
    app.UseRouting();

    // 处理/Bar路径的分支
    app.MapWhen(context => context.Request.Path.StartsWithSegments("/Bar"), barApp =>
    {
        barApp.UseSession();
        barApp.UseAuthentication();
        barApp.UseAuthorization();

        barApp.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "Bar",
                pattern: "{controller=Bar}/{action=Index}/{id?}"
            );
            endpoints.MapRazorPages();
        });
    });

    // 处理其他路径的分支
    app.MapWhen(context => !context.Request.Path.StartsWithSegments("/Bar"), defaultApp =>
    {
        defaultApp.UseSession();

        defaultApp.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Site}/{id?}"
            );
            endpoints.MapRazorPages();
        });
    });
}

这种方式下,非/Bar路径的分支不会执行认证中间件,进一步减少不必要的开销。

内容的提问来源于stack exchange,提问作者Ken Newman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 14:35:55