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

能否不使用反向代理,在同一ASP.NET应用中让Identity Server 4与MVC客户端共享同URL?

实现同一URL下IdentityServer4与MVC客户端的路径分离(无需反向代理)

当然可以实现!而且完全不需要依赖Nginx这类反向代理工具,在ASP.NET应用内部就能搞定,下面给你两种可行的方案,根据你的部署需求来选:

方案一:将IdentityServer4和MVC客户端集成到同一个ASP.NET应用中(推荐,完全无反向代理)

这种方案把两个服务合并到一个应用里,通过路由映射区分不同路径,直接共享同一端口和域名,完美符合你的需求。

步骤1:配置项目依赖

确保你的ASP.NET项目安装了IdentityServer4、Microsoft.AspNetCore.Mvc以及相关认证包。

步骤2:配置服务(Startup.cs -> ConfigureServices)

同时注册IdentityServer和MVC的服务,以及更新OIDC认证配置:

public void ConfigureServices(IServiceCollection services)
{
    // 配置IdentityServer4(使用内存配置示例,你可以替换为自己的持久化方案)
    services.AddIdentityServer()
        .AddInMemoryClients(Config.Clients)
        .AddInMemoryIdentityResources(Config.IdentityResources)
        .AddInMemoryApiScopes(Config.ApiScopes)
        .AddTestUsers(TestUsers.Users)
        .AddDeveloperSigningCredential();

    // 注册MVC控制器
    services.AddControllersWithViews();

    // 配置MVC客户端的认证
    services.AddAuthentication(options => 
    { 
        options.DefaultScheme = "Cookies"; 
        options.DefaultChallengeScheme = "oidc"; 
    }) 
    .AddCookie("Cookies") 
    .AddOpenIdConnect("oidc", options => 
    { 
        options.SignInScheme = "Cookies"; 
        // Authority指向同一应用内的IdentityServer路径
        options.Authority = "http://localhost/id"; 
        options.RequireHttpsMetadata = false; 
        options.ClientId = "mvc"; 
        options.ClientSecret = "secret"; 
        options.ResponseType = "code id_token"; 
        options.SaveTokens = true; 
        options.GetClaimsFromUserInfoEndpoint = true; 
        options.Scope.Add("api1"); 
        options.Scope.Add("offline_access");
        // 回调路径要对应MVC客户端的/api前缀
        options.CallbackPath = "/api/signin-oidc";
        options.SignedOutCallbackPath = "/api/signout-callback-oidc";
    });
}

步骤3:配置中间件与路由映射(Startup.cs -> Configure)

使用Map方法为两个服务分别指定路径前缀:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseStaticFiles();
    app.UseRouting();

    // 映射IdentityServer到/id路径
    app.Map("/id", idApp =>
    {
        idApp.UseIdentityServer();
        idApp.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.MapIdentityServer();
        });
    });

    // 映射MVC客户端到/api路径
    app.Map("/api", apiApp =>
    {
        apiApp.UseAuthentication();
        apiApp.UseAuthorization();

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

步骤4:更新IdentityServer的客户端配置

确保你的客户端配置中,回调地址等参数对应MVC的新路径:

// Config.cs中的Clients配置
new Client
{
    ClientId = "mvc",
    ClientSecrets = { new Secret("secret".Sha256()) },
    AllowedGrantTypes = GrantTypes.Hybrid,
    // 更新回调地址
    RedirectUris = { "http://localhost/api/signin-oidc" },
    PostLogoutRedirectUris = { "http://localhost/api/signout-callback-oidc" },
    AllowedScopes = { "openid", "profile", "api1" },
    AllowOfflineAccess = true
}

方案二:两个独立应用,通过PathBase区分路径(需不同端口)

如果坚持要把两个服务做成独立应用,也可以通过UsePathBase中间件为每个应用指定路径前缀,但这种方式下两个应用需要运行在不同端口,若要共享同一端口仍需反向代理,因此更推荐方案一。

IdentityServer4应用配置

在Startup的Configure方法中添加路径前缀:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...其他中间件
    app.UsePathBase("/id");
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapIdentityServer();
    });
}

MVC客户端应用配置

同样添加路径前缀,并更新认证配置中的Authority和回调地址:

// Configure方法
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...其他中间件
    app.UsePathBase("/api");
    app.UseRouting();

    app.UseAuthentication();
    app.UseAuthorization();

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

// ConfigureServices中的认证配置
services.AddAuthentication(options => 
{ 
    options.DefaultScheme = "Cookies"; 
    options.DefaultChallengeScheme = "oidc"; 
}) 
.AddCookie("Cookies") 
.AddOpenIdConnect("oidc", options => 
{ 
    options.SignInScheme = "Cookies"; 
    // Authority指向IdentityServer的地址+路径
    options.Authority = "http://localhost:5001/id"; // 假设IdentityServer运行在5001端口
    options.RequireHttpsMetadata = false; 
    options.ClientId = "mvc"; 
    options.ClientSecret = "secret"; 
    options.ResponseType = "code id_token"; 
    options.SaveTokens = true; 
    options.GetClaimsFromUserInfoEndpoint = true; 
    options.Scope.Add("api1"); 
    options.Scope.Add("offline_access");
    options.CallbackPath = "/signin-oidc"; // UsePathBase会自动加上/api前缀
    options.SignedOutCallbackPath = "/signout-callback-oidc";
});

注意事项

  • 方案二中两个应用必须使用不同端口,若要共享同一端口则还是需要反向代理,这就违背了你不想用代理的需求,因此更推荐方案一。
  • 无论哪种方案,都要确保IdentityServer的客户端配置中的所有URL参数(RedirectUris、PostLogoutRedirectUris等)与MVC客户端的实际路径一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:57:57