我有一个HttpClient,我正在使用一个REST API。但是,我在设置授权标头时遇到了麻烦。我需要将标头设置为我从执行OAuth请求中接收到的令牌。 我看到了一些。net的代码,建议如下:

httpClient.DefaultRequestHeaders.Authorization = new Credential(OAuth.token);

然而,凭据类在WinRT中不存在。有人知道如何设置授权头吗?


当前回答

我在寻找一个好的方法来处理这个问题,我也在考虑同样的问题。希望这个答案能帮助到每个和我一样有同样问题的人。

using (var client = new HttpClient())
{
    var url = "https://www.theidentityhub.com/{tenant}/api/identity/v1";
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
    var response = await client.GetStringAsync(url);
    // Parse JSON response.
    ....
}

参考来自https://www.theidentityhub.com/hub/Documentation/CallTheIdentityHubApi

其他回答

如果你想重用HttpClient,建议不要使用DefaultRequestHeaders,因为它们是用来发送每个请求的。

你可以试试这个:

var requestMessage = new HttpRequestMessage
    {
        Method = HttpMethod.Post,
        Content = new StringContent("...", Encoding.UTF8, "application/json"),
        RequestUri = new Uri("...")
    };

requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Basic", 
    Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes($"{user}:{password}")));

var response = await _httpClient.SendAsync(requestMessage);

Firstly, I wouldn't use HttpClient directly. It's too easy to make mistakes - particularly in the area of headers. The DefaultHeadersCollection is not immutable and not thread-safe because other parts of the app can change the headers on you. It's best to set the headers when you make the call. If you are working with an abstraction, and that is recommended because the classes in this area are a bit of a mess, you would want to have a headers collection and put those on your HttpRequestMessage before you send it. You need to make sure you put the content headers on the content, and not the message.

代码引用

foreach (var headerName in request.Headers.Names)
{
    //"Content-Type"
    if (string.Compare(headerName, HeadersExtensions.ContentTypeHeaderName, StringComparison.OrdinalIgnoreCase) == 0)
    {
        //Note: not sure why this is necessary...
        //The HttpClient class seems to differentiate between content headers and request message headers, but this distinction doesn't exist in the real world...
        //TODO: Other Content headers
        httpContent?.Headers.Add(HeadersExtensions.ContentTypeHeaderName, request.Headers[headerName]);
    }
    else
    {
        httpRequestMessage.Headers.Add(headerName, request.Headers[headerName]);
    }
}

下面是一个数据结构,您可以使用它来发送包含头部的请求。

代码引用

public interface IRequest
{
    CancellationToken CancellationToken { get; }
    string? CustomHttpRequestMethod { get; }
    IHeadersCollection Headers { get; }
    HttpRequestMethod HttpRequestMethod { get; }
    AbsoluteUrl Uri { get; }
}

public interface IRequest<TBody> : IRequest
{
    TBody? BodyData { get; }
}

和,一个头文件集合:

代码引用

public sealed class HeadersCollection : IHeadersCollection
{
    #region Fields
    private readonly IDictionary<string, IEnumerable<string>> dictionary;
    #endregion

    #region Public Constructors

    public HeadersCollection(IDictionary<string, IEnumerable<string>> dictionary) => this.dictionary = dictionary;

    public HeadersCollection(string key, string value) : this(ImmutableDictionary.CreateRange(
                new List<KeyValuePair<string, IEnumerable<string>>>
                {
                    new(key, ImmutableList.Create(value))
                }
                ))
    {
    }

    #endregion Public Constructors

    #region Public Properties
    public static HeadersCollection Empty { get; } = new HeadersCollection(ImmutableDictionary.Create<string, IEnumerable<string>>());
    public IEnumerable<string> Names => dictionary.Keys;
    IEnumerable<string> IHeadersCollection.this[string name] => dictionary[name];
    #endregion Public Properties

    #region Public Methods
    public bool Contains(string name) => dictionary.ContainsKey(name);

    public IEnumerator<KeyValuePair<string, IEnumerable<string>>> GetEnumerator() => dictionary.GetEnumerator();

    IEnumerator IEnumerable.GetEnumerator() => dictionary.GetEnumerator();
    public override string ToString() => string.Join("\r\n", dictionary.Select(kvp => $"{kvp.Key}: {string.Join(", ", kvp.Value)}\r\n"));
    #endregion
}

在这里查看所有工作代码和示例。

我在寻找一个好的方法来处理这个问题,我也在考虑同样的问题。希望这个答案能帮助到每个和我一样有同样问题的人。

using (var client = new HttpClient())
{
    var url = "https://www.theidentityhub.com/{tenant}/api/identity/v1";
    client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
    var response = await client.GetStringAsync(url);
    // Parse JSON response.
    ....
}

参考来自https://www.theidentityhub.com/hub/Documentation/CallTheIdentityHubApi

我是这样做的:

using (HttpClient httpClient = new HttpClient())
{
   Dictionary<string, string> tokenDetails = null;
   var messageDetails = new Message { Id = 4, Message1 = des };
   HttpClient client = new HttpClient();
   client.BaseAddress = new Uri("http://localhost:3774/");
   var login = new Dictionary<string, string>
       {
           {"grant_type", "password"},
           {"username", "sa@role.com"},
           {"password", "lopzwsx@23"},
       };
   var response = client.PostAsync("Token", new FormUrlEncodedContent(login)).Result;
   if (response.IsSuccessStatusCode)
   {
      tokenDetails = JsonConvert.DeserializeObject<Dictionary<string, string>>(response.Content.ReadAsStringAsync().Result);
      if (tokenDetails != null && tokenDetails.Any())
      {
         var tokenNo = tokenDetails.FirstOrDefault().Value;
         client.DefaultRequestHeaders.Add("Authorization", "Bearer " + tokenNo);
         client.PostAsJsonAsync("api/menu", messageDetails)
             .ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode());
      }
   }
}

这个you-tube视频帮了我大忙。请查看一下。 https://www.youtube.com/watch?v=qCwnU06NV5Q

方法是这样的,

httpClient.DefaultRequestHeaders.Authorization =
    new AuthenticationHeaderValue("Bearer", "Your Oauth token");