You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 6 API缺失Access-Control-Allow-Origin头及认证问题排查

解决.NET 6 Azure AD Web API跨域与认证问题

一、修复跨域(CORS)与HTTPS重定向冲突

你的307错误核心是中间件顺序错误:UseHttpsRedirection在CORS之前执行时,重定向响应不会携带CORS头,导致前端跨域校验失败。正确的中间件顺序必须保证CORS最先处理请求,后续的重定向、认证操作才能继承CORS头。

正确的Program.cs配置

var builder = WebApplication.CreateBuilder(args);

// 1. 配置CORS策略,允许前端源携带凭证
builder.Services.AddCors(options =>
{
    options.AddPolicy("AllowReactFrontend", policy =>
    {
        policy.WithOrigins("http://localhost:3001")
              .AllowAnyHeader()
              .AllowAnyMethod()
              .AllowCredentials(); // 必须开启,因为请求携带Authorization令牌
    });
});

// 2. 添加Azure AD认证服务
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"));

// 3. 配置授权规则
builder.Services.AddAuthorization();

builder.Services.AddControllers();

var app = builder.Build();

// 中间件顺序严格遵循:CORS → HTTPS重定向 → 认证 → 授权 → 路由
app.UseCors("AllowReactFrontend");
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

二、解决401未授权(Scope为空)问题

日志显示"Scope为空",说明令牌缺少API要求的权限范围,或API未配置Scope校验。

1. 确认Azure AD权限配置

  • 登录Azure门户,找到你的API应用注册,在公开API中确认已定义有效Scope(例如api://{API客户端ID}/access_as_user)。
  • 找到前端的Web应用注册,在API权限中添加上述Scope,并完成管理员同意(测试环境可手动同意,生产环境需管理员操作)。

2. 在API中强制校验Scope

在Program.cs的认证配置中添加Scope验证逻辑:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(options =>
    {
        builder.Configuration.Bind("AzureAd", options);
        // 验证令牌中的Scope是否包含API要求的权限
        options.Events = new JwtBearerEvents
        {
            OnTokenValidated = context =>
            {
                var scopes = context.Principal.FindFirst("scp")?.Value;
                if (string.IsNullOrEmpty(scopes) || !scopes.Contains("access_as_user"))
                {
                    context.Fail("令牌缺少API所需权限范围");
                }
                return Task.CompletedTask;
            }
        };
    },
    options => builder.Configuration.Bind("AzureAd", options));

也可以通过授权策略统一管控:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ApiAccessPolicy", policy =>
    {
        policy.RequireAuthenticatedUser();
        policy.RequireClaim("scp", "access_as_user"); // 替换为你的API Scope
    });
});

然后在控制器/Action上添加[Authorize(Policy = "ApiAccessPolicy")]注解。

3. 前端令牌获取校验

确保前端用MSAL.js等库获取令牌时,指定API的完整Scope:

// MSAL.js示例:获取API专用令牌
const tokenRequest = {
    scopes: ["api://{你的API客户端ID}/access_as_user"]
};
const tokenResponse = await msalInstance.acquireTokenSilent(tokenRequest);
// 请求API时携带:Authorization: Bearer ${tokenResponse.accessToken}

三、额外检查项

  • 确认launchSettings.json中API的applicationUrl为HTTPS地址(例如https://localhost:5220),前端直接请求HTTPS地址可避免重定向触发的额外问题。
  • 检查浏览器开发者工具的网络面板:确认请求头包含Origin: http://localhost:3001和正确的Authorization头,响应头包含Access-Control-Allow-Origin: http://localhost:3001。

内容的提问来源于stack exchange,提问作者cs.kali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:00:17