微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 IdentityModel.AspNetCore 时的授权标头

如何解决使用 IdentityModel.AspNetCore 时的授权标头

我正在使用 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 标头为空。所以我很困惑这是如何工作的。我预计它将使用不记名令牌详细信息设置 Authorization 标头值。那么这是如何工作的呢? IdentityModel 如何设置不记名令牌? (API 正确授权,好像我更改了客户端密码,它会给出 401)

解决方法

.NET Framework 允许您将 DelegatingHandler 附加到 HttpClient 以拦截和修改请求和响应。在您发送请求后,它会经过一堆处理程序,然后才真正通过网络发送。

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(在重定向的情况下很有用)


进一步参考:

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。