2016-02-29 57 views
5

我有以下设置:C#如何在一个cookie通过使用共享的HttpClient

JS客户端 - >网络API - >网络API

我需要一路下行发送身份验证的cookie 。我的问题是从一个网络API发送到另一个。由于与使用FormsAuthentication的旧系统集成,我必须传递auth cookie。

出于性能的原因我在以下词典共享HttpClients的列表(一个用于每个web API):

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

所以给定的标识符我可以抓住对应的HttpClient。

下面的作品,但我敢肯定,这是不好的代码:

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

请告诉我错了,这是:1)它似乎是错误的操纵请求DefaultRequestHeaders; 2)潜在的2个simultanious请求可能会混淆cookie,因为HttpClient是共享的。

我一直在寻找一段时间没有找到解决方案,因为大多数有匹配的问题实例化每个请求的HttpClient,因此能够设置所需的标题,我试图避免。

有一次,我得到了使用HttpResponseMessage的请求。也许这对解决方案有启发作用。

所以我的问题是:有没有一种方法可以为使用HttpClient的单个请求设置Cookie,这对于使用相同实例的其他客户端来说是安全的?

回答

11

而不是调用PutAsJsonAsync(),您可以使用HttpRequestMessage和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: 为了确保您的HTTP客户端不会储存你需要做的这个响应的Cookie:

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

否则,如果您使用一个客户端并共享其他cookie,您可能会收到意想不到的行为。

+0

非常感谢!看起来我已经非常接近了,但是你已经超越了终点。一个问题:是否有可能让GET请求使用stringcontent?如果我的'jsonDataToSend'是一个复杂的对象,它不会传递它,但如果我自己将它转换为查询字符串并将它作为'method'传递它就可以工作。将很高兴有一个通用的方法:) – Casper

+0

np :)通常GET不包含正文,但它不被规范禁止。你可以使用'new ObjectContent (value,new JsonMediaTypeFormatter(),“application/json”)'而不是'StringContent' –