2016-02-29 28 views
5

Mam następujący skonfigurować:C# Jak przekazać cookie stosując wspólny HttpClient

JS klient -> Web API -> Web Api

muszę wysłać plik cookie auth całą drogę w dół . Mój problem polega na wysyłaniu go z jednego interfejsu API do drugiego. Ze względu na integrację ze starszym systemem, który korzysta z FormsAuthentication, muszę przekazać plik cookie uwierzytelniania.

Ze względu na wydajność dzielę listę HttpClients (po jednym dla każdego API web) w następującym słownika:

private static ConcurrentDictionary<ApiIdentifier, HttpClient> _clients = new ConcurrentDictionary<ApiIdentifier, HttpClient>(); 

Więc podano identyfikator mogę złapać odpowiedni HttpClient.

następujące prace, ale jestem pewien, że to zły kod:

HttpClient client = _clients[identifier]; 
var callerRequest = HttpContext.Current.Items["MS_HttpRequestMessage"] as HttpRequestMessage; 
string authCookieValue = GetAuthCookieValue(callerRequest); 

if (authCookieValue != null) 
{ 
    client.DefaultRequestHeaders.Remove("Cookie"); 
    client.DefaultRequestHeaders.Add("Cookie", ".ASPXAUTH=" + authCookieValue); 
} 

HttpResponseMessage response = await client.PutAsJsonAsync(methodName, dataToSend); 

// Handle response... 

Co złego jest to, że: 1) wydaje się nie tak manipulować DefaultRequestHeaders we wniosku oraz 2) potencjalnie dwa simultanious wnioski może zepsuć pliki cookie, ponieważ udostępniany jest HttpClient.

Szukałem od jakiegoś czasu, nie znajdując rozwiązania, ponieważ większość osób ma problem z tworzeniem HttpClient dla każdego żądania, dlatego jest w stanie ustawić wymagane nagłówki, których próbuję uniknąć.

W pewnym momencie otrzymałem żądania pracy przy użyciu HttpResponseMessage. Być może to może być inspiracją do rozwiązania.

Moje pytanie brzmi: czy istnieje sposób ustawienia plików cookie dla pojedynczego żądania za pomocą HttpClient, który będzie bezpieczny dla innych klientów używających tego samego wystąpienia?

Odpowiedz

11

Zamiast wywoływać PutAsJsonAsync() można użyć HttpRequestMessage i SendAsync():

Uri requestUri = ...; 
HttpMethod method = HttpMethod.Get /*Put, Post, Delete, etc.*/; 
var request = new HttpRequestMessage(method, requestUri); 
request.Headers.TryAddWithoutValidation("Cookie", ".ASPXAUTH=" + authCookieValue); 
request.Content = new StringContent(jsonDataToSend, Encoding.UTF8, "application/json"); 
var response = await client.SendAsync(request); 

UPDATE: Aby upewnić się, że klient HTTP nie przechowuje żadnych plików cookie z odpowiedzią trzeba to zrobić:

var httpClient = new HttpClient(new HttpClientHandler() { UseCookies = false; }); 

W przeciwnym razie może wystąpić nieoczekiwane zachowanie za pomocą jednego klienta i udostępniania innych plików cookie.

+0

Dziękuję bardzo! Byłem naprawdę blisko, ale wydaje się, że przekroczyłeś linię mety. Jedno pytanie: czy jest możliwe, aby żądanie GET również korzystało ze specyfikacji string? Jeśli mój 'jsonDataToSend' jest złożonym obiektem, nie przekazuje go dalej, ale jeśli skonwertuję go na kwerenering i przekazuję go jako' metodę' działa. Byłoby miło mieć ogólną metodę :) – Casper

+0

np :) Zazwyczaj GET nie zawiera ciała, ale nie jest zabronione przez specyfikację. Możesz użyć 'nowej ObjectContent (value, new JsonMediaTypeFormatter()," application/json ")' zamiast 'StringContent' –