.NET Core 6长时运行函数的异步HTTP API实现及认证等疑问
异步HTTP API + Azure Functions 解决方案
问题1:Azure Functions复用原项目JWT认证规则
完全可以复用,推荐采用Azure Functions隔离进程模型(更贴近ASP.NET Core生态),直接移植原项目的认证配置:
实现步骤
- 在Function项目中添加
Microsoft.AspNetCore.Authentication.JwtBearer包,版本和原项目保持一致。 - 创建
Startup.cs,继承FunctionsStartup,复制原项目的认证注册逻辑:
using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; public class Startup : FunctionsStartup { public override void Configure(IFunctionsHostBuilder builder) { builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { // 完全复制原项目的JWT配置 options.Authority = "https://your-auth-provider.com"; options.Audience = "your-api-audience"; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true // 其他参数如IssuerSigningKey等,和原项目完全一致 }; }); builder.Services.AddAuthorization(); } }
- 在Function方法上添加
[Authorize]特性,即可实现和原项目完全相同的认证授权规则:
[Authorize] [FunctionName("LongRunningTask")] public async Task<IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, ILogger log) { // 仅持有合法JWT令牌的请求可进入 var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value; // 后续逻辑 }
如果使用进程内模型,可手动验证JWT令牌:提取请求头中的Authorization令牌,用原项目的验证逻辑校验,通过后再处理业务。
问题2:主项目控制器代理请求至Azure Functions是否合理?
这种方式可行,但并非最优解,需权衡以下点:
优点
- 认证逻辑集中在主项目,Function无需暴露给外部,仅接受主项目的调用,安全性更高。
- 主项目可统一请求入口,便于后续扩展路由、限流等逻辑。
缺点
- 增加了中间代理层,提升了架构复杂度,多一层网络调用可能带来延迟。
- 主项目仍需处理请求转发逻辑,无法完全剥离异步任务的负担。
代理实现示例
主项目控制器中通过HttpClient调用Function,用Function访问密钥(或Azure AD服务主体)做身份验证:
[Authorize] [ApiController] [Route("api/tasks")] public class TaskProxyController : ControllerBase { private readonly HttpClient _httpClient; private readonly IConfiguration _config; public TaskProxyController(HttpClient httpClient, IConfiguration config) { _httpClient = httpClient; _config = config; } [HttpPost] public async Task<IActionResult> SubmitLongRunningTask([FromBody] TaskPayload payload) { // 主项目已完成JWT认证,现在调用Function var functionUrl = _config["AzureFunctions:LongRunningTaskUrl"]; var functionKey = _config["AzureFunctions:FunctionAccessKey"]; _httpClient.DefaultRequestHeaders.Add("x-functions-key", functionKey); var response = await _httpClient.PostAsJsonAsync(functionUrl, payload); if (!response.IsSuccessStatusCode) { return StatusCode((int)response.StatusCode); } var taskResult = await response.Content.ReadFromJsonAsync<TaskResponse>(); return Ok(taskResult); } }
更优实现方案
针对5-20分钟的长时间任务,推荐采用Durable Functions + 直接客户端调用的架构:
核心架构
- Durable Functions:专门用于处理长时间运行的工作流,自动管理任务状态、重试、超时,无需手动维护队列和状态存储。
- 客户端直接调用:Function复用原项目JWT认证,客户端用原令牌直接访问Function,省去代理层。
- 状态持久化:Durable Functions自动将任务状态存储在Azure Storage中,可通过内置的状态查询端点让客户端获取进度。
Durable Functions示例
- 创建Orchestrator Function(编排任务):
[FunctionName("LongRunningTaskOrchestrator")] public async Task<TaskResult> RunOrchestrator( [OrchestrationTrigger] IDurableOrchestrationContext context) { var payload = context.GetInput<TaskPayload>(); // 调用活动Function处理耗时任务 var result = await context.CallActivityAsync<string>("LongRunningTaskActivity", payload); return new TaskResult { TaskId = context.InstanceId, Result = result, Status = "Completed" }; }
- 创建Activity Function(执行实际耗时工作):
[FunctionName("LongRunningTaskActivity")] public async Task<string> RunActivity( [ActivityTrigger] TaskPayload payload, ILogger log) { // 执行5-20分钟的耗时操作,比如数据处理、文件生成等 await DoHeavyWork(payload); return "处理完成"; }
- 创建HTTP触发的启动端点:
[Authorize] [FunctionName("StartLongRunningTask")] public async Task<IActionResult> StartTask( [HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequest req, [DurableClient] IDurableOrchestrationClient client, ILogger log) { var payload = await req.ReadFromJsonAsync<TaskPayload>(); var instanceId = await client.StartNewAsync("LongRunningTaskOrchestrator", payload); return client.CreateCheckStatusResponse(req, instanceId); }
客户端调用StartLongRunningTask后,会立即得到包含任务ID和状态查询URL的响应,后续可通过该URL轮询任务进度,或配置WebHook接收完成通知。
关键注意事项
- Function超时配置:高级计划/专用计划下,Azure Functions最长超时可设为60分钟;若任务超过60分钟,必须用Durable Functions拆分任务。
- 安全加固:若采用客户端直接调用,确保Function的JWT配置和原项目完全一致,避免非法访问;若用代理,限制Function的IP访问范围仅允许主项目的App Service IP。
- 错误处理:为耗时任务添加重试逻辑,Durable Functions支持自动重试,可配置重试策略。
内容的提问来源于stack exchange,提问作者Musius
相关产品推荐
相关产品推荐

