HttpClient身份验证标头未被发送

Ros*_*oss 23 c# wcf-web-api .net-4.5 dotnet-httpclient

我正在尝试使用HttpClient需要基本HTTP身份验证的第三方服务.我正在使用AuthenticationHeaderValue.这是我到目前为止所提出的:

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
        new RequestType("third-party-vendor-action"),
        MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
        string.Format("{0}:{1}", "username", "password"))));

var task = client.PostAsync(Uri, request.Content);
ResponseType response = task.ContinueWith(
    t =>
    {
        return t.Result.Content.ReadAsAsync<ResponseType>();
    }).Unwrap().Result;
Run Code Online (Sandbox Code Playgroud)

看起来POST动作工作正常,但我没有收到我期望的数据.通过一些试验和错误,并最终使用Fiddler来嗅探原始流量,我发现授权标头没有被发送.

我已经看过,但我认为我已经将指定的身份验证方案指定为AuthenticationHeaderValue构造函数的一部分.

有没有我错过的东西?

Hai*_*yen 32

您的代码看起来应该可以工作 - 我记得遇到类似的问题设置Authorization标头并通过执行Headers.Add()而不是设置它来解决:

request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password"))));
Run Code Online (Sandbox Code Playgroud)

更新: 看起来像是在执行请求时.内容,并非所有标头都反映在内容对象中.你可以通过检查request.Headers和request.Content.Headers来看到这一点.您可能想要尝试的一件事是使用SendAsync而不是PostAsync.例如:

HttpRequestMessage<RequestType> request = 
     new HttpRequestMessage<RequestType>(
         new RequestType("third-party-vendor-action"),
         MediaTypeHeaderValue.Parse("application/xml"));

request.Headers.Authorization = 
    new AuthenticationHeaderValue(
        "Basic", 
        Convert.ToBase64String(
            System.Text.ASCIIEncoding.ASCII.GetBytes(
                string.Format("{0}:{1}", "username", "password"))));

 request.Method = HttpMethod.Post;
 request.RequestUri = Uri;
 var task = client.SendAsync(request);

 ResponseType response = task.ContinueWith(
     t => 
         { return t.Result.Content.ReadAsAsync<ResponseType>(); })
         .Unwrap().Result;
Run Code Online (Sandbox Code Playgroud)


Nit*_*wal 19

这也可以,你不必处理base64字符串转换:

var handler = new HttpClientHandler();
handler.Credentials = new System.Net.NetworkCredential("username", "password");
var client = new HttpClient(handler);
...
Run Code Online (Sandbox Code Playgroud)


Dav*_*den 17

尝试在客户端上设置标题:

DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password))));
Run Code Online (Sandbox Code Playgroud)

这适合我.

  • 对于使用该客户端实例发出的所有请求,是的.您是否使用相同的客户端访问具有不同身份验证方案的端点?即,您是否在客户端实例上设置BaseAddress? (3认同)
  • 这可能会起作用,但它会为所有请求设置授权标头,不是吗?这是不可取的。 (2认同)

Sor*_*ren 8

另外,请考虑如果您的请求被重定向, Redirect-Handler清除Authorization 标头。
因此,如果您调用 HTTP 端点并将其重定向到 HTTPS 端点,您将丢失授权标头。

request.Headers.Authorization = null;
Run Code Online (Sandbox Code Playgroud)

框架:.NET v6.0


小智 6

实际上你的问题是PostAsync- 你应该使用SendAsync. 在您的代码中 -client.PostAsync(Uri, request.Content);仅发送不包含请求消息标头的内容。正确的方法是:

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url)
{
    Content = content
};
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
httpClient.SendAsync(message);
Run Code Online (Sandbox Code Playgroud)

  • 谢谢你一千次。我花了几个小时尝试将标头附加到 HttpClient 并使用 GetAsync 和 PostAsync 等,总的来说,我发现 WebAPI 很痛苦(给我 ServiceStack!!) (2认同)