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

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

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


当前回答

Oauth流程是复杂的,总是有一个或另一个错误的空间。 我的建议是始终使用样板代码和一组用于OAuth身份验证流的库。这会让你的生活更轻松。

下面是库集的链接。用于。net的OAuth库

其他回答

static async Task<AccessToken> GetToken()
{
        string clientId = "XXX";
        string clientSecret = "YYY";
        string credentials = String.Format("{0}:{1}", clientId, clientSecret);

        using (var client = new HttpClient())
        {
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.UTF8.GetBytes(credentials)));
            List<KeyValuePair<string, string>> requestData = new List<KeyValuePair<string, string>>();
            requestData.Add(new KeyValuePair<string, string>("grant_type", "client_credentials"));
            FormUrlEncodedContent requestBody = new FormUrlEncodedContent(requestData);
            var request = await client.PostAsync("https://accounts.spotify.com/api/token", requestBody);
            var response = await request.Content.ReadAsStringAsync();
            return JsonConvert.DeserializeObject<AccessToken>(response);
        }
    }

使用基本授权和Json参数。

using (HttpClient client = new HttpClient())
{
    var request_json = "your json string";

    var content = new StringContent(request_json, Encoding.UTF8, "application/json");

    var authenticationBytes = Encoding.ASCII.GetBytes("YourUsername:YourPassword");

    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",
            Convert.ToBase64String(authenticationBytes));
    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

    var result = await client.PostAsync("YourURL", content);

    var result_string = await result.Content.ReadAsStringAsync();
}

我是这样做的:

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

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
}

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

我在设置不记名代币

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

它在一个端点上起作用,但在另一个端点上不起作用。问题是我在"持票人"上用了小写b。改变后,现在它工作的两个api的我正在击中。如果你甚至不把它看作是寻找针的干草堆之一,这是一件很容易错过的事情。

一定要有“持票人”,要有资本。