如何排除 ASP.NET Core 5 中的特定路径,以便请求由 ASP.NET 而不是静态文件处理?
How to exclude a specific path in ASP.NET Core 5 so that the request is processed by ASP.NET and not by the static files?
所以我在 Angular
中有一个 frontend/SPA,在 ASP.NET Core 5
中有一个 backend/API。构建前端后,构建文件被复制到后端的 wwwroot 文件夹。
我在后端使用 OpenIDConnect 实现了身份验证流程。这是由前端触发并导致后端端点。因此,您将被重定向到身份提供者并返回到 ASP.NET 提供的回调端点。
现在,当我打开网站时,ASP.NET 为我提供静态 Angular 文件,这会将我重定向到启动 Login/Auth 进程的端点。该过程最终将我重定向到 https://localhost:5001/callback
.
现在的问题是 ASP.NET 没有通过预先配置的 callback
路径为请求提供服务。它将请求转发到静态文件,因此 Angular 将处理请求。
所以我的问题是:是否可以排除特定路径,以便通过 ASP.NET 而不是静态文件来处理它们?
到目前为止,我已经尝试拦截请求并仅转发路径中没有 /api 或 /callback 的内容。如这些 blogs/questions:
中所述
- https://www.blinkingcaret.com/2018/01/24/angular-and-asp-net-core/
- https://weblog.west-wind.com/posts/2020/Jul/12/Handling-SPA-Fallback-Paths-in-a-Generic-ASPNET-Core-Server
- My SPA files are giving 404 errors when serving the SPA in a branch of the request pipeline. How do I make my static files available to my SPA?
ConfigureServices
在我的 Startup.cs
中看起来像这样:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "backend", Version = "v1" });
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(2);
options.SlidingExpiration = true;
options.Cookie.MaxAge = TimeSpan.FromHours(2);
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => ConfigureOpenIdConnect(options));
services.AddControllersWithViews();
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "wwwroot";
});
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin();
builder.AllowAnyHeader();
builder.AllowAnyMethod();
});
});
}
我的 Configure
看起来像这样:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "backend v1"));
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseCors();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}");
});
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSpa(spa =>
{
spa.Options.SourcePath = "../../frontend/";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "dev:start");
}
});
}
private void ConfigureOpenIdConnect(OpenIdConnectOptions options)
{
options.Authority = Configuration.GetValue<string>("Authority");
options.ClientId = Configuration.GetValue<string>("ClientId");
options.ClientSecret = Configuration.GetValue<string>("ClientSecret");
// Set response type to code
options.ResponseMode = OpenIdConnectResponseMode.FormPost;
// Configure the scope
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
options.CallbackPath = new PathString("/callback");
// This saves the tokens in the session cookie
options.SaveTokens = true;
options.UseTokenLifetime = false;
}
更新 1:
ASP.NET project
的文件夹结构:
wwwroot
的文件夹结构:
这些是 Angular 构建文件。
在 assets
文件夹中是字体和一些图像
好的,我找到了问题的解决方案。我之前没有注意到的是,我正在获取回调路由的 HTTP 200 代码。通常您可能会收到重定向的 HTTP 302。
最后发现是Angular PWA
的service worker中断了请求。我真的不知道为什么,但是当我从 app.module.ts
中删除 ServiceWorker
时,它又起作用了。
所以我在 Angular
中有一个 frontend/SPA,在 ASP.NET Core 5
中有一个 backend/API。构建前端后,构建文件被复制到后端的 wwwroot 文件夹。
我在后端使用 OpenIDConnect 实现了身份验证流程。这是由前端触发并导致后端端点。因此,您将被重定向到身份提供者并返回到 ASP.NET 提供的回调端点。
现在,当我打开网站时,ASP.NET 为我提供静态 Angular 文件,这会将我重定向到启动 Login/Auth 进程的端点。该过程最终将我重定向到 https://localhost:5001/callback
.
现在的问题是 ASP.NET 没有通过预先配置的 callback
路径为请求提供服务。它将请求转发到静态文件,因此 Angular 将处理请求。
所以我的问题是:是否可以排除特定路径,以便通过 ASP.NET 而不是静态文件来处理它们?
到目前为止,我已经尝试拦截请求并仅转发路径中没有 /api 或 /callback 的内容。如这些 blogs/questions:
中所述- https://www.blinkingcaret.com/2018/01/24/angular-and-asp-net-core/
- https://weblog.west-wind.com/posts/2020/Jul/12/Handling-SPA-Fallback-Paths-in-a-Generic-ASPNET-Core-Server
- My SPA files are giving 404 errors when serving the SPA in a branch of the request pipeline. How do I make my static files available to my SPA?
ConfigureServices
在我的 Startup.cs
中看起来像这样:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "backend", Version = "v1" });
});
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
options.Cookie.SameSite = SameSiteMode.Strict;
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(2);
options.SlidingExpiration = true;
options.Cookie.MaxAge = TimeSpan.FromHours(2);
})
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, options => ConfigureOpenIdConnect(options));
services.AddControllersWithViews();
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "wwwroot";
});
services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder.AllowAnyOrigin();
builder.AllowAnyHeader();
builder.AllowAnyMethod();
});
});
}
我的 Configure
看起来像这样:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "backend v1"));
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseCors();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller}/{action}/{id?}");
});
app.UseDefaultFiles();
app.UseStaticFiles();
app.UseSpa(spa =>
{
spa.Options.SourcePath = "../../frontend/";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "dev:start");
}
});
}
private void ConfigureOpenIdConnect(OpenIdConnectOptions options)
{
options.Authority = Configuration.GetValue<string>("Authority");
options.ClientId = Configuration.GetValue<string>("ClientId");
options.ClientSecret = Configuration.GetValue<string>("ClientSecret");
// Set response type to code
options.ResponseMode = OpenIdConnectResponseMode.FormPost;
// Configure the scope
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("offline_access");
options.CallbackPath = new PathString("/callback");
// This saves the tokens in the session cookie
options.SaveTokens = true;
options.UseTokenLifetime = false;
}
更新 1:
ASP.NET project
的文件夹结构:
wwwroot
的文件夹结构:
这些是 Angular 构建文件。
在 assets
文件夹中是字体和一些图像
好的,我找到了问题的解决方案。我之前没有注意到的是,我正在获取回调路由的 HTTP 200 代码。通常您可能会收到重定向的 HTTP 302。
最后发现是Angular PWA
的service worker中断了请求。我真的不知道为什么,但是当我从 app.module.ts
中删除 ServiceWorker
时,它又起作用了。