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

如何从IdentityServer4或Cookie获取AccessToken并在MVC客户端发送至API

获取AccessToken并在HttpClient中使用的方案

嘿,我来帮你搞定这个问题!你的MVC客户端基于IdentityServer4+Cookie认证,要给API请求附加AccessToken,这里有两种实用的方法,推荐优先用第一种框架原生的方式:


方法一:使用ASP.NET Core的IAccessTokenProvider(推荐)

ASP.NET Core针对OIDC客户端场景提供了IAccessTokenProvider接口,可以直接获取有效的AccessToken,还会自动处理令牌刷新,非常省心。

步骤1:确认OIDC配置

首先确保你的Startup/Program.cs里的OIDC配置已经开启了SaveTokens,这是保存令牌到Cookie的关键:

services.AddAuthentication(options =>
{
    options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
    options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
    options.Authority = "https://your-identityserver-url";
    options.ClientId = "your-mvc-client-id";
    options.ClientSecret = "your-client-secret";
    options.ResponseType = "code";
    options.Scope.Add("your-api-scope"); // 必须包含API所需的权限范围
    options.SaveTokens = true; // 开启后,令牌会被保存到Cookie的认证票据中
});

步骤2:注入服务并获取令牌

在你的HttpClient所属的服务类中,注入IAccessTokenProvider和IHttpContextAccessor,然后修改你的方法:

private readonly HttpClient _httpClient;
private readonly IAccessTokenProvider _tokenProvider;
private readonly IHttpContextAccessor _httpContextAccessor;

// 构造函数注入依赖
public YourMenuService(HttpClient httpClient, IAccessTokenProvider tokenProvider, IHttpContextAccessor httpContextAccessor)
{
    _httpClient = httpClient;
    _tokenProvider = tokenProvider;
    _httpContextAccessor = httpContextAccessor;
}

public async Task<IList<MenuModel>> GetMenusNavAsync()
{
    // 请求AccessToken,指定需要的API权限范围
    var tokenResult = await _tokenProvider.RequestAccessToken(new AccessTokenRequestOptions
    {
        Scopes = new[] { "your-api-scope" },
        HttpContext = _httpContextAccessor.HttpContext
    });

    // 校验令牌获取结果
    if (!tokenResult.TryGetToken(out var accessToken))
    {
        // 令牌获取失败,可触发认证挑战或抛出异常
        await _httpContextAccessor.HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
        return null;
    }

    // 将令牌附加到请求头
    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken.Value);

    var response = await _httpClient.GetAsync("api/Menu/GetMenusNavBar");
    response.EnsureSuccessStatusCode();
    using var responseContent = await response.Content.ReadAsStreamAsync();
    return await JsonSerializer.DeserializeAsync<List<MenuModel>>(responseContent);
}

方法二:从Cookie认证票据中直接提取(不推荐)

如果不想用框架原生的令牌管理,也可以直接从当前用户的认证票据中提取AccessToken,但这种方式不会自动处理令牌刷新,需要手动维护过期逻辑:

public async Task<IList<MenuModel>> GetMenusNavAsync(IHttpContextAccessor httpContextAccessor)
{
    var httpContext = httpContextAccessor.HttpContext;
    if (httpContext == null)
    {
        throw new InvalidOperationException("无法获取HttpContext");
    }

    // 从认证票据的声明中提取AccessToken
    var accessToken = httpContext.User.FindFirst("access_token")?.Value;
    if (string.IsNullOrEmpty(accessToken))
    {
        // 令牌不存在,触发认证挑战
        await httpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme);
        return null;
    }

    // 附加到请求头
    _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);

    var response = await _httpClient.GetAsync("api/Menu/GetMenusNavBar");
    response.EnsureSuccessStatusCode();
    using var responseContent = await response.Content.ReadAsStreamAsync();
    return await JsonSerializer.DeserializeAsync<List<MenuModel>>(responseContent);
}

注意:这种方法同样需要OIDC配置中开启SaveTokens = true,否则认证票据里不会包含AccessToken。


关键提醒

  • 务必确认OIDC配置的Scope包含API所需的权限,否则获取到的令牌会被API拒绝。
  • 优先使用第一种方法,IAccessTokenProvider会自动处理令牌过期刷新、权限校验等场景,减少手动维护的工作量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:42:50