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

如何在.NET通用主机中注册OpenAPI生成的OAuth2 TokenProvider?

依赖注入注册TokenProvider示例

1. 配置文件参数(appsettings.json)

先在配置文件中添加OAuth2相关参数:

{
  "OAuth": {
    "ClientId": "your-client-id",
    "ClientSecret": "your-client-secret",
    "TokenEndpoint": "https://your-auth-server/oauth2/token"
  },
  "ApiBaseUrl": "https://your-api-base-url/"
}

2. 配置绑定类

创建类映射OAuth配置项:

public class OAuthClientOptions
{
    public string ClientId { get; set; } = string.Empty;
    public string ClientSecret { get; set; } = string.Empty;
    public string TokenEndpoint { get; set; } = string.Empty;
}

3. 核心注册代码

在Generic Host的Program.cs中完成依赖注入配置:

var builder = Host.CreateDefaultBuilder(args);

builder.ConfigureServices((context, services) =>
{
    // 绑定OAuth配置到实体类
    services.Configure<OAuthClientOptions>(context.Configuration.GetSection("OAuth"));

    // 注册TokenProvider实现(需实现生成代码中的TokenProvider<OAuthToken>接口)
    services.AddSingleton<TokenProvider<OAuthToken>, ClientCredentialsTokenProvider<OAuthToken>>();

    // 注册生成的API客户端,注入TokenProvider并添加OAuth消息处理器
    services.AddHttpClient<YourGeneratedApiClient>(client =>
    {
        client.BaseAddress = new Uri(context.Configuration["ApiBaseUrl"]!);
    })
    .AddHttpMessageHandler(provider => 
        new OAuthAuthorizationHandler(provider.GetRequiredService<TokenProvider<OAuthToken>>()));
});

var host = builder.Build();
await host.RunAsync();

4. TokenProvider实现示例

如果生成代码未提供默认实现,可自行实现接口:

public class ClientCredentialsTokenProvider : TokenProvider<OAuthToken>
{
    private readonly HttpClient _httpClient;
    private readonly OAuthClientOptions _options;
    private OAuthToken? _currentToken;

    public ClientCredentialsTokenProvider(HttpClient httpClient, IOptions<OAuthClientOptions> options)
    {
        _httpClient = httpClient;
        _options = options.Value;
    }

    public async Task<OAuthToken> GetTokenAsync(CancellationToken cancellationToken = default)
    {
        // 检查token有效性,过期则重新获取
        if (_currentToken == null || DateTime.UtcNow >= _currentToken.ExpiresAt)
        {
            var request = new HttpRequestMessage(HttpMethod.Post, _options.TokenEndpoint)
            {
                Content = new FormUrlEncodedContent(new Dictionary<string, string>
                {
                    {"grant_type", "client_credentials"},
                    {"client_id", _options.ClientId},
                    {"client_secret", _options.ClientSecret}
                })
            };

            var response = await _httpClient.SendAsync(request, cancellationToken);
            response.EnsureSuccessStatusCode();

            _currentToken = await response.Content.ReadFromJsonAsync<OAuthToken>(cancellationToken);
            if (_currentToken != null)
            {
                // 预留60秒缓冲时间,避免token过期
                _currentToken.ExpiresAt = DateTime.UtcNow.AddSeconds(_currentToken.ExpiresIn - 60);
            }
        }

        return _currentToken ?? throw new InvalidOperationException("Failed to obtain OAuth token");
    }
}

5. OAuth请求消息处理器

自动为API请求添加Authorization头:

public class OAuthAuthorizationHandler : DelegatingHandler
{
    private readonly TokenProvider<OAuthToken> _tokenProvider;

    public OAuthAuthorizationHandler(TokenProvider<OAuthToken> tokenProvider)
    {
        _tokenProvider = tokenProvider;
    }

    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var token = await _tokenProvider.GetTokenAsync(cancellationToken);
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.AccessToken);

        return await base.SendAsync(request, cancellationToken);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:22:44