能否不使用反向代理,在同一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
相关产品推荐
相关产品推荐

