【问题标题】:HttpClient authentication header not getting sent未发送 HttpClient 身份验证标头
【发布时间】:2012-04-09 17:38:57
【问题描述】:

我正在尝试将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;

看起来 POST 操作工作正常,但我没有取回我期望的数据。经过反复试验,最终使用 Fiddler 嗅探原始流量,我发现授权标头没有被发送。

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

有什么我错过的吗?

【问题讨论】:

    标签: c# .net-4.5 wcf-web-api dotnet-httpclient


    【解决方案1】:

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

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

    更新: 看起来当您执行 request.Content 时,并非所有标头都反映在内容对象中。您可以通过检查 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;
    

    【讨论】:

    • 我尝试了类似的方法,request.Headers.Authorization 得到了相同的结果。这让我有点头疼,因为我不完全确定下一步该尝试什么。我知道 MVC4 beta 和 4.5 预览版在某些方面直接不兼容 - 我想知道这是否与它有关?
    • 您的更新似乎至少发送了授权标头。我还不能从第三方服务中检索数据(可能我错过了请求正文中的其他错误),但至少正确的标头正在通过网络。这是一个开始。谢谢!
    • ASCII 还是 UTF-8?见stackoverflow.com/questions/11743160/…
    【解决方案2】:

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

    var handler = new HttpClientHandler();
    handler.Credentials = new System.Net.NetworkCredential("username", "password");
    var client = new HttpClient(handler);
    ...
    

    【讨论】:

    • 比编码 UID:PWD 组合更简洁的解决方案。
    【解决方案3】:

    尝试在客户端设置header:

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

    这对我有用。

    【讨论】:

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

    实际上你的问题在于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);
    

    【讨论】:

    • 一千次谢谢。我花了几个小时尝试将标头附加到 HttpClient 并使用 GetAsync 和 PostAsync 等,而且总的来说我发现 WebAPI 很痛苦(给我 ServiceStack !!)
    【解决方案5】:

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

    request.Headers.Authorization = null;
    

    框架:NETv6

    【讨论】:

      猜你喜欢
      • 2019-02-21
      • 1970-01-01
      • 1970-01-01
      • 2022-10-25
      • 2012-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多