我有以下设置:
JS客户端 - > Web Api - > Web Api
我需要一直向下发送auth cookie。我的问题是从一个web 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)当共享HttpClient时,可能两个同时发送的请求可能会弄乱cookie。
我一直在寻找一段时间而没有找到解决方案,因为大多数具有匹配问题的实例化每个请求的HttpClient,因此能够设置所需的标头,我试图避免。
有一次,我收到使用HttpResponseMessage
的请求。也许这可以激发解决方案。
所以我的问题是:有没有办法使用HttpClient为单个请求设置cookie,这对于使用相同实例的其他客户端是否安全?
答案 0 :(得分:16)
您可以使用HttpRequestMessage和SendAsync()来代替调用PutAsJsonAsync():
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);
更新: 要确保您的HTTP客户端不存储响应中的任何cookie,您需要执行此操作:
var httpClient = new HttpClient(new HttpClientHandler() { UseCookies = false; });
否则,您可能会因使用一个客户端并共享其他Cookie而出现意外行为。