编辑:代码仓库这里。
此外,我知道我可以简单地将
.DisableAntiforgery();
添加到我的 API 端点(如here所述)以使其正常工作,但我想以正确的方式执行此操作。
我正在尝试使用 Http POST 调用将文件从客户端的 Blazor 组件上传到后端 Minimal API 端点,但经过多次失败的尝试,我在此处发布此问题。
我首先在我的后端 API 中尝试了这个,如记录的这里:
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
// Do my thing
}
});
使用 Swagger UI 将请求发送到后端 API:
我遇到了这个错误:😩
System.InvalidOperationException: Endpoint HTTP: POST /upload_many contains anti-forgery metadata, but a middleware was not found that supports anti-forgery.
Configure your application startup by adding app.UseAntiforgery() in the application startup code. If there are calls to app.UseRouting() and app.UseEndpoints(...), the call to app.UseAntiforgery() must go between them. Calls to app.UseAntiforgery() must be placed after calls to app.UseAuthentication() and app.UseAuthorization().
at Microsoft.AspNetCore.Routing.EndpointMiddleware.ThrowMissingAntiforgeryMiddlewareException(Endpoint endpoint)
at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
然后我尝试了这个。
Program.cs
在我的后端 API 中:
//...
builder.Services.AddAntiforgery();
//...
var app = builder.Build();
//...
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
// Do my thing here
}
});
//...
我遇到了这个错误:😫
Microsoft.AspNetCore.Http.BadHttpRequestException: Invalid anti-forgery token found when reading parameter "IFormFileCollection myFiles" from the request body as form.
---> Microsoft.AspNetCore.Antiforgery.AntiforgeryValidationException: The required antiforgery cookie ".AspNetCore.Antiforgery.JitzV0NlXkw" is not present.
at Microsoft.AspNetCore.Antiforgery.DefaultAntiforgery.ValidateRequestAsync(HttpContext httpContext)
at Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)
--- End of inner exception stack trace ---
at Microsoft.AspNetCore.Http.RequestDelegateFactory.Log.InvalidAntiforgeryToken(HttpContext httpContext, String parameterTypeName, String parameterName, Exception exception, Boolean shouldThrow)
at Microsoft.AspNetCore.Http.RequestDelegateFactory.<HandleRequestBodyAndCompileRequestDelegateForForm>g__TryReadFormAsync|102_0(HttpContext httpContext, String parameterTypeName, String parameterName, Boolean throwOnBadRequest)
at Microsoft.AspNetCore.Http.RequestDelegateFactory.<>c__DisplayClass102_2.<<HandleRequestBodyAndCompileRequestDelegateForForm>b__2>d.MoveNext()
--- End of stack trace from previous location ---
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Antiforgery.Internal.AntiforgeryMiddleware.InvokeAwaited(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
我开始认为我做得不对。我在文档中找不到工作示例。
我在经历了this之后发现了这一点。
完整源代码这里。
根据文档,为了能够上传文件,您需要授权标头、客户端证书或 Cookie 标头。
为了满足该要求,我决定通过文件上传 POST 请求传递防伪令牌。
现在我的 API 端点如下所示:
// Get token
app.MapGet("antiforgery/token", (IAntiforgery forgeryService, HttpContext context) =>
{
var tokens = forgeryService.GetAndStoreTokens(context);
var xsrfToken = tokens.RequestToken!;
return TypedResults.Content(xsrfToken, "text/plain");
});
//.RequireAuthorization(); // In a real world scenario, you'll only give this token to authorized users
// Add my file upload endpoint
app.MapPost("/upload_many", async (IFormFileCollection myFiles) =>
{
foreach (var file in myFiles)
{
// ...
}
return TypedResults.Ok("Ayo, I got your files!");
});
所以我现在有 2 个端点:上传文件
第1步: 获取令牌。
步骤2.1: 在对上传端点进行 POST 调用之前,添加您从步骤 1 收到的 XSRF 令牌。
步骤2.1: 添加您要上传的文件。 pickle.png 在我的例子中。
步骤2.3: 点击发送。此时,您就可以成功拨打电话了。