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

如何为ASP.NET Core添加多认证?解决API外部调用无用户输入问题

实现无用户交互的API调用解决方案

你的问题根源在于当前配置的OpenID Connect用户认证是面向用户交互场景的,当匿名请求触发认证逻辑时会重定向到Azure AD登录页,而Postman这类无浏览器客户端无法处理这种跳转。下面是几种可行的解决方案,按推荐优先级排序:

一、Azure AD客户端凭据(服务账号)认证(推荐生产环境使用)

这是Azure生态中标准的服务对服务调用方式,无需用户参与:

1. Azure AD侧配置

  • 给你的API注册Azure AD应用,设置应用ID URI(例如api://your-api-client-id)
  • 添加应用权限(选择Application类型,而非Delegated),并完成管理员同意
  • 注册一个服务账号(独立Azure AD应用),生成客户端密钥或证书,用于获取令牌

2. 修改Startup.cs的认证配置

保留原有用户认证逻辑的同时,添加Bearer认证以支持服务令牌验证:

services.AddAuthentication()
    // 保留原有的用户认证(用于Swagger/用户交互场景)
    .AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
    {
        options.Cookie.Path = Configuration["SiteConfiguration:BasePath"];
        options.Cookie.Domain = Configuration["SiteConfiguration:Domain"];
    })
    .AddMicrosoftIdentityWebApp(Configuration.GetSection("AzureAd"),
        OpenIdConnectDefaults.AuthenticationScheme,
        "V3Cookie")
    // 新增服务对服务的Bearer认证
    .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));

// 配置授权策略,允许两种认证方式
services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(
            CookieAuthenticationDefaults.AuthenticationScheme,
            JwtBearerDefaults.AuthenticationScheme)
        .Build();
});

3. 配置appsettings.json的Azure AD参数

确保AzureAd节点包含以下内容:

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "TenantId": "你的租户ID",
    "ClientId": "API的Azure AD应用ID",
    "Audience": "api://你的API应用ID" // 和之前设置的应用ID URI一致
}

4. Postman调用步骤

  • 先获取令牌:向https://login.microsoftonline.com/{租户ID}/oauth2/v2.0/token发送POST请求,参数:
    • grant_type: client_credentials
    • client_id: 服务账号的应用ID
    • client_secret: 服务账号的客户端密钥
    • scope: api://你的API应用ID/.default
  • 调用API时,在请求头添加Authorization: Bearer {获取到的令牌}

二、API密钥认证(快速临时方案)

如果不需要Azure AD的复杂配置,可以快速实现密钥验证:

1. 自定义API密钥认证逻辑

在Startup.cs中添加:

// 注册API密钥认证方案
services.AddAuthentication("ApiKey")
    .AddScheme<ApiKeyAuthOptions, ApiKeyAuthHandler>("ApiKey", options =>
    {
        options.ValidApiKey = Configuration["ApiSettings:ValidKey"];
    });

// 配置授权策略,支持多种认证方式
services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder()
        .RequireAuthenticatedUser()
        .AddAuthenticationSchemes(
            CookieAuthenticationDefaults.AuthenticationScheme,
            "ApiKey")
        .Build();
});

// 自定义认证选项和处理器
public class ApiKeyAuthOptions : AuthenticationSchemeOptions
{
    public string ValidApiKey { get; set; }
}

public class ApiKeyAuthHandler : AuthenticationHandler<ApiKeyAuthOptions>
{
    public ApiKeyAuthHandler(IOptionsMonitor<ApiKeyAuthOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock)
        : base(options, logger, encoder, clock) { }

    protected override Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        if (!Request.Headers.TryGetValue("X-Api-Key", out var headerValues))
            return Task.FromResult(AuthenticateResult.NoResult());

        var providedKey = headerValues.FirstOrDefault();
        if (providedKey != Options.ValidApiKey)
            return Task.FromResult(AuthenticateResult.Fail("无效的API密钥"));

        var identity = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, "服务账号") }, Scheme.Name);
        var ticket = new AuthenticationTicket(new ClaimsPrincipal(identity), Scheme.Name);
        return Task.FromResult(AuthenticateResult.Success(ticket));
    }
}

2. 配置API密钥

在appsettings.json中添加:

"ApiSettings": {
    "ValidKey": "生成一个随机的复杂密钥"
}

3. Postman调用

在请求头添加X-Api-Key: 你的密钥即可调用API

三、临时关闭特定接口认证(仅测试用)

如果只是临时测试,可以给目标接口添加[AllowAnonymous]属性,跳过认证重定向:

[AllowAnonymous]
[HttpGet("your-endpoint")]
public IActionResult GetYourData()
{
    // 接口逻辑
}

注意:生产环境禁止大量使用该方式,会引入安全风险。


内容的提问来源于stack exchange,提问作者kpolewaczyk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 02:40:38