部署到Azure的Asp.Net Core Web API仅报错时触发CORS策略问题
问题分析与解决方案
问题本质
正常请求时,ASP.NET Core的CORS中间件会正确添加Access-Control-Allow-Origin头,跨域请求正常;但当API抛出未处理异常时,要么请求未走完完整中间件管道,要么Azure返回的默认错误页面未携带CORS头,导致浏览器触发跨域拦截。
解决方案
1. 全局异常捕获,确保错误响应带CORS头
在Program.cs中添加全局异常处理中间件,包裹业务逻辑中间件,保证即使抛出异常,响应也能携带CORS头。调整管道顺序如下:
var app = builder.Build(); var logger = app.Services.GetRequiredService<ILogger<Program>>(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseCors(allowAnyOriginsPolicyName); // 添加全局异常处理中间件 app.Use(async (context, next) => { try { await next(); // 处理4xx状态码(如401、404),确保CORS头存在 if (context.Response.StatusCode >= 400 && context.Response.StatusCode < 600) { if (!context.Response.Headers.ContainsKey("Access-Control-Allow-Origin")) { context.Response.Headers.Append("Access-Control-Allow-Origin", "*"); } } } catch (Exception ex) { logger.LogError(ex, "服务器未处理异常"); context.Response.StatusCode = StatusCodes.Status500InternalServerError; context.Response.ContentType = "application/json"; // 手动添加CORS头 if (!context.Response.Headers.ContainsKey("Access-Control-Allow-Origin")) { context.Response.Headers.Append("Access-Control-Allow-Origin", "*"); } await context.Response.WriteAsJsonAsync(new { message = "服务器处理请求出错" }); } }); app.UseAuthentication(); app.UseAuthorization(); app.MapControllers(); app.Run();
2. 控制器内捕获业务异常
修改AssignController的ByEmail方法,捕获业务逻辑中的异常,返回标准HTTP响应,确保响应经过CORS中间件处理:
[HttpGet] [Route("ByEmail")] public IActionResult ByEmail(string clientEmail, string managerEmail) { try { new ManagerOps(_logger, _configuration).AssignToClientByEmail(clientEmail, managerEmail); return Ok(true); } catch (Exception ex) { _logger.LogError(ex, $"分配失败,clientEmail: {clientEmail}, managerEmail: {managerEmail}"); return BadRequest(new { message = "邮箱不存在或无效,分配失败" }); } }
3. 关闭Azure App Service默认错误页
在Azure门户进入你的App Service:
- 导航到配置 > 常规设置
- 找到错误页面选项,设置为关闭
- 避免Azure返回自带的无CORS头的错误页面
4. 修正客户端JS语法错误
你的axios代码中catch块语法有误,修正后才能正确捕获错误响应:
axios({ method: type, url: serverAndEndPoint, headers : {"Authorization" : `Bearer ${response.accessToken}`}, params : params, data : data }) .then(response2 => { console.log(response2); console.log(response2.data); logMessageTime(JSON.stringify(response2.data)); return response2.data; }, reject => { console.log("reject"); console.log(reject); }) .catch(error => { console.log("error caught in apiExec promise"); console.log(error); })
内容的提问来源于stack exchange,提问作者David Sopko
相关产品推荐
相关产品推荐

