2016-02-29 13 views
5

ho il seguente set up:C# Come passare su un cookie utilizzando un comune HttpClient

client JS -> Web Api -> Web Api

ho bisogno di inviare il cookie di autenticazione fino in fondo . Il mio problema è inviarlo da una web API a un'altra. A causa dell'integrazione con un sistema precedente, che utilizza FormsAuthentication, devo passare il cookie auth.

Per motivi di prestazioni condivido una lista di HttpClients (uno per ogni Web API) nel dizionario seguente:

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

Quindi dato un identificatore posso afferrare il corrispondente HttpClient.

i seguenti lavori, ma sono abbastanza sicuro che questo è il codice cattivo:

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... 

Che cosa è sbagliato di questo è che 1) mi sembra sbagliato per manipolare DefaultRequestHeaders in una richiesta e 2) potenzialmente due richieste simultanious potrebbe rovinare i cookie, poiché HttpClient è condiviso.

Ho cercato un po 'di tempo senza trovare una soluzione, poiché la maggior parte dei problemi di corrispondenza crea un'istanza di HttpClient per ogni richiesta, quindi è possibile impostare le intestazioni richieste, che sto cercando di evitare.

A un certo punto ho ricevuto richieste di lavoro utilizzando uno HttpResponseMessage. Forse può essere di ispirazione per una soluzione.

Quindi la mia domanda è: esiste un modo per impostare i cookie per una singola richiesta utilizzando un HttpClient, che sarà al sicuro da altri client che utilizzano la stessa istanza?

risposta

11

Invece di chiamare PutAsJsonAsync() è possibile utilizzare HttpRequestMessage e 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); 

AGGIORNAMENTO: Per assicurarsi che il client HTTP non memorizza i cookie da una risposta che devi fare questo:

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

In caso contrario si potrebbe ottenere un comportamento imprevisto utilizzando un client e condividendo altri cookie.

+0

Grazie mille! Sono stato molto vicino, sembra, ma sei arrivato al traguardo. Una domanda: è possibile che la richiesta GET usi anche il contenuto di stringhe? Se il mio 'jsonDataToSend' è un oggetto complesso, non lo passa, ma se lo converto in una querystring e lo passo come' metodo' funziona. Sarebbe bello avere un metodo generico :) – Casper

+0

np :) Solitamente GET non contiene il corpo, ma non è proibito dalle specifiche. Puoi usare 'new ObjectContent (valore, new JsonMediaTypeFormatter()," application/json ")' invece di 'StringContent' –

Problemi correlati