如何在每次调用`CreateClient`时刷新Bearer标记(可能通过覆盖`CreateClient`)。

问题描述 投票:0回答:1

我想利用 IHttpClientFactory 第一次在.NET Core 3.1 MVC项目中使用。我使用的是 HttpClient 来调用Microsoft Graph API。

每当我需要对API进行调用时,我需要首先检查应用程序所拥有的验证令牌是否有效(即没有过期),如果无效,则使用刷新令牌来获取新的验证令牌。

在了解 IHttpClientFactory 我在初始化一个 HttpClient 为我的应用程序,然后每当我需要进行API调用时,我会首先调用我自己的 PrepareHttpClient() 函数,所以它会像这样。

public class MyController : Controller
{
    private static HttpClient httpClient = new HttpClient();
    private readonly IOAuthService _oAuthService;

    public MyController(IOAuthService oAuthService)
    {
        _oAuthService = oAuthService;
    }

    public async Task<IActionResult> Index()
    {
        var url = "http://whatever";
        await PrepareHttpClient();
        var response = await httpClient.GetAsync(url);
        // Other stuff
    }

    private async Task PrepareHttpClient()
    {
        httpClient.DefaultRequestHeaders.Clear();
        string bearerToken = await _oAuthService.GetOAuthBearerToken();
        httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {bearerToken}");
    }
}

The GetOAuthBearerToken 函数在一个服务中,如您所见,它被注入到控制器中,它基本上是在检查当前令牌是否过期,如果需要,则获取一个新的令牌,并将有效的令牌作为字符串返回。我认为该函数的完整代码在这里没有必要,但如果需要的话,我可以添加。

在了解了 IHttpClientFactory 和事实,你可以给一个 HttpClient 名称,并将其配置在 Startup.cs 我想:"好啊,我就打电话给 GetOAuthBearerToken 函数配置客户端时"。类似于

services.AddHttpClient("OneDrive", async(c) => {
    string bearerToken = await IOAuthService.GetOAuthBearerToken();
    c.DefaultRequestHeaders.Add("Authorization", $"Bearer {bearerToken}");
});

然而,这样做存在一些问题。

  1. 将一个服务注入到 Startup 类似乎是不可能的,这是有道理的,所以我不能注入我的 IOAuthService 就像我在控制器中做的那样。
  2. GetOAuthBearerToken 本身使用 HttpClient 来获取更新的API令牌,并使用DI注入一个 IHttpClientFactory 的函数中,而这个函数本身也被注入到 Startup 听起来像... 我失去了理智。

最终我意识到这些都不重要,因为我需要在每次调用时检查和刷新API令牌,而不仅仅是在应用程序启动时实例化客户端时。所以,在我看来,最优雅的解决方案是覆盖 CreateClient 方法中 IHttpClientFactory在每次调用API之前,我都会调用它,这样它就可以调用我的 GetOAuthBearerToken 函数,然后我就会知道,每次调用 CreateClientHttpClient 是好的,头中有一个有效的承载令牌。

我的问题是(最后!),我如何覆盖掉 CreateClient 以这种方式?假设这是实现我的目的的最好方法。

c# asp.net-core dotnet-httpclient
1个回答
0
投票

对不起,如果有人能把这个作为评论。

我注意到的第一件事是你忘记了清除头,并为每个请求添加新的头,为你在启动时注册的实例。

编辑:我就先去回答一下。对不起,我没有任何形式的c#编译器和intellisense。

public class MyController : Controller
{
    private static IHttpClientFactory httpClientFactory = new IHttpClientFactory();
    private readonly IOAuthService _oAuthService;

    public MyController(IOAuthService oAuthService,IHttpClientFactory myfactory)
    {
        _oAuthService = oAuthService;
        httpClientFactory = myfactory;
    }

    public async Task<IActionResult> Index()
    {
        var url = "http://whatever";
        HttpClient myclient = httpClientFactory.CreateClient("MyNamedClient");
        var response = await HttpClient.GetAsync(url);
        // Other stuff
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.