.NET6-使用中间件根据请求路由添加不同的头



我有一个应用程序,它同时具有Razor Pages和API端点。API端点的路径以"/api";。我想使用middlware添加安全头&对内联脚本使用nonce。nonce对于API终结点是不必要的,并且安全头根据请求的终结点的类型而不同。

我尝试了几种不同的方法,但仍然有问题。在我的第一次尝试(使用.Map()扩展(中,响应标头似乎从未设置,并且我试图放入HttpContext.Items的内容在Razor视图中不可用。使用我的第二种方法(使用.Use()if/else逻辑(,可以设置响应标头,但HttpContext.Items中的项不可用。

尝试#1:

Program.cs

var builder = WebApplication.CreateBuilder(args);
// logic to register services...
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization()
## CUSTOM MIDDLEWARE ##
app.Map("/api", HandleApiRequests);
app.MapFallback(HandleRazorRequests);
## END CUSTOM MIDDLEWARE ##
app.MapRazorPages();
app.Run();

这样,响应标头和HttpContext项似乎永远不会设置。

尝试#2:

Program.cs

var builder = WebApplication.CreateBuilder(args);
// logic to register services...
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization()
## CUSTOM MIDDLEWARE ##
app.Use(async (context, next) =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
HandleApiRequests(app);
}
else
{
HandleRazorRequests(app);
}
});
## END CUSTOM MIDDLEWARE ##
app.MapRazorPages();
app.Run();

这样,就设置了响应标头,但在编辑剃刀视图时,HttpContextItem不可用。

尝试之间常见

IApplicationBuilderExtensions.cs

public static void HandleRazorRequests(this IApplicationBuilder app)
{
app.UseSecurityHeaders(new SecurityHeaderOptions { IsApi = false });
}
public static void HandleApiRequests(this IApplicationBuilder app)
{
app.UseSecurityHeaders(new SecurityHeaderOptions { IsApi = true });
}
public static IApplicationBuilder UseSecurityHeaders(this IApplicationBuilder app, SecurityHeaderOptiosn options)
{
app.UseMiddleware<SecurityHeaderMiddleware>(options);
}

SecurityHeaderMiddleware.cs

public class SecurityHeaderMiddleware
{
private readonly RequestDelegate _next;
private readonly SecurityHeaderOptions _options;
public SecurityHeaderMiddleware (RequestDelegate next, SecurityHeaderOptions options)
{
this._next = next;
this._options = options;
}
public async Task InvokeAsync(HttpContext httpContext)
{
if (this._options.IsApi)
{
httpContext.Response.Headers["Content-Security-Policy"] = "my CSP for APIs";
return await this._next(httpContext);
}
httpContext.Response.Headers["Content-Security-Policy"] = "my CSP for Razor Pages";
// Add CSP Nonce to HttpContext Items dictionary so it can be used at the view-level.
httpContext.Items["csp-nonce"] = "my nonce";
await this._next(httpContext);
}
}

我能够使用.UseWhen()完成所需的结果问题。

app.UseWhen(ctx => ctx.Request.Path.StartsWithSegments("/api"), _appBuilder =>
{
// Apply middlware to manipulate context of requests
// to endpoints whose paths starts with "/api".
});
app.UseWhen(ctx => !ctx.Request.Path.StartsWithSegments("/api"), _appBuilder =>
{
// Apply middlware to manipulate context of requests
// to endpoints whose paths DO NOT start with "/api".
});

使用.Use()的问题是请求不会继续到.Use()调用下面的逻辑。它使管道分叉,再也不会回来。当您使用Use()时,您需要完成调用中的整个管道;如果它没有以.Run()结束,它将永远不会实际运行应用程序。

当您使用.UseWhen()时,您会分支并为该请求添加额外的中间件,但您会返回并继续正常的路径。

相关内容

  • 没有找到相关文章

最新更新