使用 .Net HttpClient 设置 'per request' cookie
Set 'per request' cookie with .Net HttpClient
您好,我正在尝试使用 Owin 基础结构实现简单的 http 代理服务。此代理必须使用 windows 身份验证对用户进行身份验证,从企业 AD 中提取用户属性,将此信息作为 cookie 值添加到原始请求中,然后将请求重定向到 Internet 上的应用程序(我们称之为外部应用程序)。
我正在使用 HttpClient 向外部应用程序发送请求。
但是 HttpClient 不适合这种情况。似乎唯一允许使用它发送 cookie 的方法是将它们放入 CookieContainer 并将此 CookieContainer 设置为 HttpClientHandler 的 属性。当您只有一个用户时没问题,但在代理服务的情况下,来自不同用户的 cookie 值将混合并相互覆盖。
有什么方法可以为每个请求设置 cookie 或 CookieContainer 吗?或者也许有更好的方法来重定向请求?
P.S。这是一些代码:
http 处理程序的初始化:
private void RegisterRoutes(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "Proxy",
routeTemplate: "{*path}",
handler: HttpClientFactory.CreatePipeline
(
innerHandler: new HttpClientHandler(),
handlers: new DelegatingHandler[]
{
new ProxyHandler()
}
),
defaults: new { path = RouteParameter.Optional },
constraints: null);
}
代理处理程序
内部 class 代理处理程序:委托处理程序
{
私人只读 HttpClient _client;
public ProxyHandler()
{
var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Automatic};
_client = new HttpClient(handler);
}
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var forwardUri = new UriBuilder(request.RequestUri);
forwardUri.Host = "localhost";
forwardUri.Port = 23016;
forwardUri.Scheme = Uri.UriSchemeHttp;
request.RequestUri = forwardUri.Uri;
request.Headers.Host = forwardUri.Host;
//Explicitly null it to avoid protocol violation
if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Trace)
request.Content = null;
try
{
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
//Explicitly null it to avoid protocol violation
if (request.Method == HttpMethod.Head)
response.Content = null;
return response;
}
catch (Exception ex)
{
var response = request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
string message = ex.Message;
if (ex.InnerException != null)
message += ':' + ex.InnerException.Message;
response.Content = new StringContent(message);
Trace.TraceError("Error:{0}", message);
return response;
}
}
private void SetCookies(HttpRequestMessage request)
{
var container = new CookieContainer();
var authCookieValue = "2EF91D8FD9EDC594F2DB82";
var authCookie = new Cookie("cookieByProxy", authCookieValue);
var targetUri = new Uri("http://localhost:23016/");
container.Add(targetUri, authCookie);
var cookieHeader = container.GetCookieHeader(targetUri);
if (!string.IsNullOrEmpty(cookieHeader))
request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);//Overwriting cookie header with custom values. However cookie values are ignored by HttpClient (both old and new)
}
}
在此处找到解决方案:
诀窍是将 HttpClientHandler 的 UseCookie 标志显式设置为 false.
var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Automatic, UseCookie = false };
您好,我正在尝试使用 Owin 基础结构实现简单的 http 代理服务。此代理必须使用 windows 身份验证对用户进行身份验证,从企业 AD 中提取用户属性,将此信息作为 cookie 值添加到原始请求中,然后将请求重定向到 Internet 上的应用程序(我们称之为外部应用程序)。
我正在使用 HttpClient 向外部应用程序发送请求。
但是 HttpClient 不适合这种情况。似乎唯一允许使用它发送 cookie 的方法是将它们放入 CookieContainer 并将此 CookieContainer 设置为 HttpClientHandler 的 属性。当您只有一个用户时没问题,但在代理服务的情况下,来自不同用户的 cookie 值将混合并相互覆盖。
有什么方法可以为每个请求设置 cookie 或 CookieContainer 吗?或者也许有更好的方法来重定向请求?
P.S。这是一些代码:
http 处理程序的初始化:
private void RegisterRoutes(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "Proxy",
routeTemplate: "{*path}",
handler: HttpClientFactory.CreatePipeline
(
innerHandler: new HttpClientHandler(),
handlers: new DelegatingHandler[]
{
new ProxyHandler()
}
),
defaults: new { path = RouteParameter.Optional },
constraints: null);
}
代理处理程序 内部 class 代理处理程序:委托处理程序 { 私人只读 HttpClient _client;
public ProxyHandler()
{
var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Automatic};
_client = new HttpClient(handler);
}
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var forwardUri = new UriBuilder(request.RequestUri);
forwardUri.Host = "localhost";
forwardUri.Port = 23016;
forwardUri.Scheme = Uri.UriSchemeHttp;
request.RequestUri = forwardUri.Uri;
request.Headers.Host = forwardUri.Host;
//Explicitly null it to avoid protocol violation
if (request.Method == HttpMethod.Get || request.Method == HttpMethod.Trace)
request.Content = null;
try
{
var response = await _client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
//Explicitly null it to avoid protocol violation
if (request.Method == HttpMethod.Head)
response.Content = null;
return response;
}
catch (Exception ex)
{
var response = request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex);
string message = ex.Message;
if (ex.InnerException != null)
message += ':' + ex.InnerException.Message;
response.Content = new StringContent(message);
Trace.TraceError("Error:{0}", message);
return response;
}
}
private void SetCookies(HttpRequestMessage request)
{
var container = new CookieContainer();
var authCookieValue = "2EF91D8FD9EDC594F2DB82";
var authCookie = new Cookie("cookieByProxy", authCookieValue);
var targetUri = new Uri("http://localhost:23016/");
container.Add(targetUri, authCookie);
var cookieHeader = container.GetCookieHeader(targetUri);
if (!string.IsNullOrEmpty(cookieHeader))
request.Headers.TryAddWithoutValidation("Cookie", cookieHeader);//Overwriting cookie header with custom values. However cookie values are ignored by HttpClient (both old and new)
}
}
在此处找到解决方案:
var handler = new HttpClientHandler { ClientCertificateOptions = ClientCertificateOption.Automatic, UseCookie = false };