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

基于OpenIDConnect/OAuth2与OpenIDDict,客户端安全调用API方案

核心误区:别用认证Cookie调用API

客户端Web应用的OIDC认证Cookie是用来维持自身登录状态的,不能直接传递给API服务器做授权验证——Cookie和客户端域名绑定,跨域场景下浏览器会自动拦截,而且API服务器也无法解析客户端的Cookie(除非同域,但通常是独立服务)。正确做法是用Access Token来调用API。

客户端获取Access Token的两种常见方式

1. 授权码流+PKCE(推荐)

这是OIDC标准的安全流程,客户端完成认证时,除了获取用于身份认证的ID Token,还能拿到用于API授权的Access Token,以及用于刷新Token的Refresh Token。

配置客户端Web应用(以ASP.NET Core为例)

在Program.cs中配置OIDC时,确保请求API的权限范围(scope),并开启Token保存:

builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
    options.Authority = "https://your-auth-server.com"; // 认证服务器地址
    options.ClientId = "your-client-id";
    options.ClientSecret = "your-client-secret"; // 机密客户端需配置
    options.ResponseType = "code";
    options.Scope.Clear();
    options.Scope.Add("openid");
    options.Scope.Add("profile");
    options.Scope.Add("your-api-scope"); // 要访问的API权限范围
    options.SaveTokens = true; // 关键:将Access Token保存到Cookie中
});

2. 隐式流(不推荐,仅适配纯前端SPA)

纯前端SPA可能会用隐式流直接获取Access Token,但安全性远低于授权码流+PKCE,目前已不推荐使用。

客户端调用API的实现方式

方式一:HttpClient自动携带Access Token

ASP.NET Core提供扩展可以让HttpClient自动从当前认证上下文获取Access Token并添加到请求头:

// 注册带Token处理的HttpClient
builder.Services.AddHttpClient("ApiClient", client =>
{
    client.BaseAddress = new Uri("https://your-api-server.com");
})
.AddHttpMessageHandler<BearerTokenHandler>();

// 注册Token处理类
builder.Services.AddTransient<BearerTokenHandler>();

BearerTokenHandler实现:

public class BearerTokenHandler : DelegatingHandler
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public BearerTokenHandler(IHttpContextAccessor httpContextAccessor)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var accessToken = await _httpContextAccessor.HttpContext.GetTokenAsync("access_token");
        if (!string.IsNullOrEmpty(accessToken))
        {
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
        }
        return await base.SendAsync(request, cancellationToken);
    }
}

在控制器/服务中注入调用:

private readonly IHttpClientFactory _httpClientFactory;

public YourController(IHttpClientFactory httpClientFactory)
{
    _httpClientFactory = httpClientFactory;
}

public async Task<IActionResult> CallApi()
{
    var client = _httpClientFactory.CreateClient("ApiClient");
    var response = await client.GetAsync("/api/your-endpoint");
    response.EnsureSuccessStatusCode();
    var data = await response.Content.ReadFromJsonAsync<YourModel>();
    return View(data);
}

方式二:手动获取Access Token调用API

不用HttpClient的话,也可以手动从HttpContext取Token,然后在请求头中添加Authorization: Bearer {token}:

public async Task<IActionResult> CallApiManually()
{
    var accessToken = await HttpContext.GetTokenAsync("access_token");
    using var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    var response = await client.GetAsync("https://your-api-server.com/api/your-endpoint");
    // 处理响应逻辑
}
API服务器的验证配置

API服务器需要用OpenIDDict验证Access Token,确保请求合法:

builder.Services.AddAuthentication(options =>
{
    options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
    options.Authority = "https://your-auth-server.com";
    options.Audience = "your-api-audience"; // 需和认证服务器配置的API受众一致
    options.RequireHttpsMetadata = true;
});

// 启用授权
builder.Services.AddAuthorization();

在API控制器/方法上添加授权特性:

[ApiController]
[Route("api/[controller]")]
[Authorize]
public class YourController : ControllerBase
{
    [HttpGet]
    public IActionResult Get()
    {
        return Ok(new { Message = "API访问成功" });
    }
}
你可能遗漏的关键点
  1. 混淆认证与授权载体:客户端Cookie是自身认证用的,API需要的是授权用的Access Token,两者作用完全不同。
  2. 未配置API权限范围:客户端认证时如果没请求API的scope,认证服务器不会颁发对应Access Token。
  3. 未开启SaveTokens:ASP.NET Core的OIDC配置中,SaveTokens = true是将Access Token保存到Cookie的关键,否则后续无法获取Token。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.01 22:43:11