我遇到了类似的问题,传入的请求必须在执行之前进行身份验证。然而,我并不真正关心内容的大小(它不应该达到例如~20MB)。因此,我不确定这种方法是否真的符合您的需求。
正如您在评论中所述,OnExecutingAsync 可用于将要执行的代码放置在函数本身之前。问题是,OnExecutingAsync 只是一个任务;你不能真正从中返回任何东西 - 如果可以这样做会很好,因为它可以让我们返回例如“Unauhorized”,通常在谈论 http 请求时就是这种情况。
在任何情况下,无论它是否符合您的要求,这里是:在我看来,请求将内容作为流保存,并且 afaik 它还没有被 http 触发管道处理,至少直到你打电话给例如ReadAsStringAsync 或类似的东西。
使用实现IFunctionInvocationFilter 的 BaseController,类似于:
注意:截至 2019 年 12 月 29 日,IFunctionInvocationFilter 仍处于预览阶段。
internal abstract class BaseController : IFunctionInvocationFilter
{
protected bool _IsAuthenticated = false;
private IAuthenticationService _AuthenticationService;
protected BaseController(IAuthenticationService authenticationService)
{
_AuthenticationService = authenticationService;
}
public virtual async Task OnExecutedAsync(FunctionExecutedContext executedContext, CancellationToken cancellationToken)
{
_IsAuthenticated = false;
}
public virtual async Task OnExecutingAsync(FunctionExecutingContext executingContext, CancellationToken cancellationToken)
{
// This part is a tad flimsy, but I never managed to find a better way of retrieving the header values
// You could probably investigate the FunctionExecutingContext a tad more and see if you can come up with something better
if (executingContext.Arguments.TryGetValue("request", out var request) && request is HttpRequest httpRequest)
_IsAuthenticated = _AuthenticationService.Authenticate(httpRequest.Headers);
else
_IsAuthenticated = false;
}
protected async Task<IActionResult> DoAuthenticated(Func<Task<IActionResult>> action)
{
return !IsAuthenticated ? Unauthenticated() : await action();
}
protected virtual IActionResult Unauthenticated()
{
var someErrorHandlingWithSomeModelAsBody = ...
return new UnauthorizedObjectResult(someErrorHandlingWithSomeModelAsBody);
}
}
AuthenticationService能够判断头部中的key是否有效。
您可能已经注意到依赖注入的使用(这正是我制作的函数应用程序的实现方式),您可能可以轻松地纠正这一点,根据需要使事物变为静态。
示例控制器类似于:
public class SampleController : BaseController
{
private readonly ISampleService _SampleService;
public SampleController(ISampleService sampleService, IAuthenticationService authenticationService) : base(authenticationService)
{
_SampleService = sampleService;
}
[FunctionName(nameof(SampleFunction))]
public async Task<IActionResult> SampleFunction(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "v1/my_function")] HttpRequest request,
ILogger log)
{
try
{
return await DoAuthenticated(async () =>
{
var largeFileAsString = await request.Content.ReadAsStringAsync();
return await _SampleService.HandleLargeFile(largeFileAsString);
}
}
catch (Exception e)
{
// If you need exception handling...
}
}
}
每当SampleFunction被触发时,都会按以下顺序执行:
-
OnExecutingAsync-body
-
SampleFunction-body - 只有在 OnExecutingAsync 期间验证实际上成功时才会执行该 func
-
OnExecutedAsync-body
问题是,即使身份验证失败,该函数是否仍能处理您所说的整个 20MB 的 JSON 内容。如果您对此进行测试,我个人实际上会对结果感兴趣。