C# Refit客户端未发送授权头

4
我正在使用 C# Refit 客户端使我的服务通过 http 通信。
我尝试通过设置 Authorization 头来发送 Bearer token,但根据错误信息,请求中没有设置 AZ header(参见底部)。我已尝试通过提供所有头信息和使用 [Authorize] 属性以及他们在自述文件中描述的所有其他方法来设置它。
这是我的 Refit 客户端 API 调用定义:

[Post(PresentationsBasePath + "/{presentationId}/cart")]
Task AddItemToCartAsync(long presentationId, ShoppingCartItemView item, [HeaderCollection] IDictionary<string, string> headers);

//calling it here:

await _api.AddItemToCartAsync(presentationId, item, GetTokenHeader(presentationId, token));

private Dictionary<string, string> GetTokenHeader(long presentationId, string token) => new()
{
    ["pres_id"] = presentationId.ToString(),
    [HeaderNames.Authorization] = $"Bearer {token}",
};


然而,我收到了401错误,并且查看抛出的Refit.ApiException,发现RequestMessage.Headers中没有包含授权头信息。

以下是我注册refit api IPresentationsApi的方式。我在DI配置中未进行任何与认证相关的操作。


var refitSettings = GetRefitSettings();

void Configure<T>() where T : class => services
    .AddRefitClient<T>()
    .ConfigureHttpClient(ConfigureHttpClient);

Configure<IMarsPresentationApi>();
//other apis configured below

    
    private static void ConfigureHttpClient(IServiceProvider sp, HttpClient client)
    {
        var config = sp.GetRequiredService<IMarsConfiguration>();
        if (config.BaseUrl == null)
            throw new InvalidOperationException("Mars:BaseUrl must be configured");
        client.BaseAddress = new Uri(config.BaseUrl);
    }

这里显示了错误-您可以看到我收到了401错误,并且请求中未设置AZ头:

错误

我做错了什么?如何使其发送AZ头?


@jdweng 这些都不重要。如果我告诉我的代码在头部设置承载令牌,但它没有设置,那么其他服务器在做什么就无关紧要了。这两个服务都是我的,我知道它返回401是因为没有设置。 - DLeh
如果您不发送授权,则会失败。您的代码没有将数据授权放入请求中。它正在从请求中读取标头,这是错误的。 - jdweng
@jdweng 这正是我的问题。为什么不行呢?我设置了头部,但它没有发送。[HeaderNames.Authorization] = $"Bearer {token}", - DLeh
你的指令是反过来的。你正在执行GET而不是PUT。 - jdweng
1
@jdweng 你在说什么啊,哈哈。 我正在按照我的 Refit API 定义显式地执行 [POST] 请求。 - DLeh
显示剩余5条评论
2个回答

1

第一次尝试:

services.AddRefitClient<T>(new RefitSettings { AuthorizationHeaderValueGetter = () => Task.FromResult("TestToken") }).ConfigureHttpClient(ConfigureHttpClient);

第二次尝试:

services.AddRefitClient<T>().ConfigureHttpClient(ConfigureHttpClient).AddHttpMessageHandler<AuthorizationMessageHandler>();

其中:

  public class AuthorizationMessageHandler : DelegatingHandler
  {
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancelToken)
    {
      HttpRequestHeaders headers = request.Headers;

      AuthenticationHeaderValue authHeader = headers.Authorization;

      if (authHeader != null)
        headers.Authorization = new AuthenticationHeaderValue(authHeader.Scheme, "TestToken");
        
      return await base.SendAsync(request, cancelToken);
    }
  }

这个方法给我带来了同样的问题。一旦我调用 base.SendAsync()request.Headers 就被清空了。 - DLeh
对于AuthorizationHeaderValueGetter场景,请尝试在AddItemToCartAsync方法上添加[Headers("Authorization: Bearer")]。 - Danut Radoaica
更奇怪的是,当我将其作为API运行时它似乎可以工作,但在控制台应用程序中却不行。我已经尝试使用处理程序(handler)这种方法,当我跨越base.SendAsync()时,请求对象标头会被删除授权。我想知道是否有一些应用程序设置正在以某种方式覆盖它们,而这些设置在我的控制台应用程序中没有设置。 - DLeh

0

这个讨论在 Refit 的 GitHub 问题上继续进行。有人有用地指出,当 HttpClient 跟随重定向时,默认情况下会剥离掉授权标头 - https://github.com/reactiveui/refit/issues/1374#issuecomment-1212776451

我也遇到了同样的问题。在阅读了 GitHub 问题讨论中的建议后,我配置了我的 HttpClient 实例以禁用自动重定向。

var httpClient = new HttpClient(new HttpClientHandler() { AllowAutoRedirect = false })

这证实了服务器API向看起来正确的API端点返回301-永久移动响应,而这些端点是根据我收到的API文档构建的。

查看我如何配置我的API端点,它们被配置为/{presentationId}/cart,结尾没有斜杠。

我更新了端点以最后带有斜杠/{presentationId}/cart/,这样就停止了服务器重定向的返回。


哇,那太奇怪了...我得找机会试试看。谢谢! - DLeh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接