1

我正在使用IdentityModel.AspNetCore客户端凭据流访问受保护的 api。在我的启动中,我在下面进行了配置。

services.AddAccessTokenManagement(options =>
{
    options.Client.Clients.Add("oauth", new ClientCredentialsTokenRequest
    {
        Address = Configuration.GetValue<string>("Endpoint"),
        ClientId = Configuration.GetValue<string>("ClientId"),
        ClientSecret = Configuration.GetValue<string>("ClientSecret"),
        Scope = Configuration.GetValue<string>("Scope")
    });
});
services.AddClientAccessTokenClient("client", configureClient: client =>
{
    client.BaseAddress = new Uri(Configuration.GetValue<string>("ApiBaseUrl"));
});

在我的服务中,我正在使用一个客户端实例IHttpClientFactory

var client = clientFactory.CreateClient("client");

这段代码运行良好,我可以访问 API。我的问题是,当我扩展从 clientFactory 获得的客户端实例时,其中的 Authorization 标头为空。所以我很困惑这是如何工作的。我预计它将使用不记名令牌详细信息设置授权标头值。那么这是如何工作的呢?IdentityModel 如何设置不记名令牌?(API 正确授权,好像我更改了客户端密码,它会给出 401)

4

1 回答 1

0

.NET Framework 允许您将DelegatingHandlers 附加到 anHttpClient以拦截和修改请求和响应。在您发送请求后,它会在实际通过网络发送之前经过一堆处理程序。

public class MessageHandler1 : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        Debug.WriteLine("Process request");
        // Call the inner handler.
        var response = await base.SendAsync(request, cancellationToken);
        Debug.WriteLine("Process response");
        return response;
    }
}

IdentityModel 库的工作方式相同。它拦截请求,Authorization在发送之前添加处理程序。然后它检查响应是否有HTTP 401错误,刷新令牌并重复请求。

protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
    await SetTokenAsync(request, forceRenewal: false, cancellationToken);
    var response = await base.SendAsync(request, cancellationToken);

    // retry if 401
    if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
    {
        response.Dispose();

        await SetTokenAsync(request, forceRenewal: true, cancellationToken);
        return await base.SendAsync(request, cancellationToken);
    }

    return response;
}

https://github.com/IdentityModel/IdentityModel.AspNetCore/blob/27e966bf6729530e4a7480478f18302fe996a7f6/src/AccessTokenManagement/ClientAccessToken/ClientAccessTokenHandler.cs#L31-L46

至于Authorization似乎缺少的实际标题,您可以在HttpResponseMessage.RequestMessage属性中找到它。

从文档(强调我的):

此属性设置为导致此响应消息的请求消息。在使用 HttpClient 发送请求的情况下,此属性将指向导致最终响应的实际请求消息。请注意,这可能与用户在发送请求时提供的消息不同。如果由于重定向或身份验证需要重新发送请求,通常就是这种情况。此属性可用于确定实际创建响应的 URL(在重定向的情况下很有用)


更多参考资料:

于 2021-06-20T06:52:56.490 回答