799 Stimmen

Festlegen des Autorisierungskopfes des HttpClient

Ich habe einen HttpClient, die ich für eine REST-API verwenden. Ich habe jedoch Probleme beim Einrichten des Authorization-Headers. Ich muss den Header auf das Token setzen, das ich bei meiner OAuth-Anfrage erhalten habe. Ich sah einige Code für .NET, die das folgende vorschlägt,

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

Die Credential-Klasse existiert jedoch nicht in WinRT. Hat jemand eine Idee, wie man den Authorization Header setzt?

1voto

Sie können auch das folgende Beispiel zu verwenden, dass es IHttpClientFactory verwenden:

    readonly IHttpClientFactory _httpClientFactory;

    public HTTPClientHelper(IHttpClientFactory httpClientFactory, string clientName = null)
    {
        this._httpClientFactory = httpClientFactory;
    }

    public Task<T> GetAsync(string url, string token) {

        var client = _httpClientFactory.CreateClient(_clientName);

        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(JwtBearerDefaults.AuthenticationScheme, token);

        using (HttpResponseMessage response = await _client.GetAsync(url)){
          ......
        }
     }

1voto

Philip Johnson Punkte 1005

Ich bin auf diesen alten Thread gestoßen. Das Problem, das ich hatte, war, dass ich weiß, einen statischen HttpClient zu verwenden, aber mein Token braucht alle 59 Minuten zu aktualisieren.

Ich hätte also HttpClientFactory verwenden können, aber da eines meiner Projekte noch in .NET 4.8 war, habe ich eine Klasse erstellt, die von HttpClient geerbt hat, sodass ich in allen Projekten ähnlichen Code habe. Um das Token abrufen zu können, ist ein Geheimnis erforderlich (ich verwende identityserver4).

Ich setze das dann als Singleton in DI (ich verwende hier Ninject):

Bind<MyHttpClient>().ToMethod(c =>
{
    var accessKey = ConfigurationManager.AppSettings["AccessKey"];

    var client = new MyHttpClient(accessKey)
    {
        BaseAddress = new Uri(MyUrls.MyApiBaseUrl)
    };

    client.DefaultRequestHeaders.Accept.Clear();
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

    return client;
}).InSingletonScope();

Dann die Klasse selbst - benannt nach der API, auf die sie zugreifen soll:

public class MyHttpClient : BaseHttpClient
{
     private static readonly HttpClient _authHttpClient = new HttpClient();
     private string _secret;

     public MyHttpClient(string secret)
     {
         _secret = secret;
     }

    /// <summary>
    /// Add the token to each and every request, cached for 1 minute less than the token's lifetime
    /// </summary>
    /// <param name="request"></param>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    /// <exception cref="Exception"></exception>
    public override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
        cancellationToken.ThrowIfCancellationRequested();

        var cacheSeconds = 3600 - 60; // Default of 59 minutes

        var token = CacheHelper<string>.Get("MyToken", cacheSeconds * 60, () =>
        {
            var authorityUrl = MyUrls.AuthServerUrl;

            // discover endpoints from metadata
            DiscoveryDocumentResponse disco;
            disco = _authHttpClient.GetDiscoveryDocumentAsync(authorityUrl).Result;
            if (disco.IsError)
            {
                throw new Exception("Error getting discovery document: " + disco.Error);
            }

            // request token
            var tokenResponse = _authHttpClient.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest
            {
                Address = disco.TokenEndpoint,

                ClientId = "myapp",
                ClientSecret = _secret,
                Scope = "myapi"
            }).Result;

            if (tokenResponse.IsError)
            {
                throw new Exception("Error getting token: " + tokenResponse.Error);
            }

            if (tokenResponse.ExpiresIn < cacheSeconds + 60)
            {
                throw new Exception($"Token expires in {tokenResponse.ExpiresIn}s, which is less than {cacheSeconds + 60}");
            }

            if (tokenResponse.ExpiresIn > cacheSeconds + 60)
            {
                Log.Warn().Message($"Token expiry in {tokenResponse.ExpiresIn}s, which is greater than {cacheSeconds}").Write();
            }

            return tokenResponse.AccessToken;
        });

        // THIS IS THE BIT - Assign this inside a SendAsync override and you are done!
        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
        return base.SendAsync(request, cancellationToken);
    }

}

Schließlich, nur der Vollständigkeit halber, sieht meine CacheHelper-Klasse wie folgt aus:

public static class CacheHelper<T>
{
    private static readonly object _locker = new object();

    public static T Get(string cacheName, int cacheTimeoutSeconds, Func<T> func)
    {
        var obj = MemoryCache.Default.Get(cacheName, null);
        if (obj != null) return (T)obj;

        lock (_locker)
        {
            obj = MemoryCache.Default.Get(cacheName, null);
            if (obj == null)
            {
                obj = func();
                var cip = new CacheItemPolicy
                {
                    AbsoluteExpiration = new DateTimeOffset(DateTime.UtcNow.AddSeconds(cacheTimeoutSeconds))
                };
                MemoryCache.Default.Set(cacheName, obj, cip);
            }
        }

        return (T)obj;
    }
}

0voto

Khurram Jamil Punkte 1

Der Oauth-Prozessablauf ist komplex und es gibt immer Raum für den einen oder anderen Fehler. Ich schlage vor, immer den Boilerplate-Code und eine Reihe von Bibliotheken für den OAuth-Authentifizierungsablauf zu verwenden, um Ihnen das Leben zu erleichtern.

Hier ist der Link zu den Bibliotheken. OAuth-Bibliotheken für .Net

0voto

Ewan Punkte 1241

Wenn Sie den Debug-Modus von Visual Studio IISExpress verwenden und eine Verbindung zum HTTP-Port statt zum HTTPS-Port herstellen, kann es vorkommen, dass die Auth-Header ausgelassen werden.

Wechseln Sie zur SLL-Verbindung, und sie werden wieder angezeigt.

Möglicherweise leitet das Setup den http-Verkehr um, und das führt dazu, dass die Autorisierung entfernt wird.

-1voto

saurabh seth Punkte 1
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);
        }
    }

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X