简洁版本
如果要重用 NTLM 身份验证连接,请使用 .NET Core 2.1
长版
我很惊讶地发现,当使用 NTLM 身份验证时,“旧”HttpClient 确实为每个请求使用不同的连接。这不是一个错误 - 在 .NET Core 2.1 HttpClient 之前,它将使用 HttpWebRequest,它会在每次经过 NTLM 身份验证的调用后关闭连接。
这在文档中进行了描述HttpWebRequest.UnsafeAuthenticatedConnectionSharing可用于启用连接共享的属性:
该属性的默认值为 false,这会导致当前连接在请求完成后关闭。您的应用程序每次发出新请求时都必须执行身份验证序列。
如果此属性设置为 true,则用于检索响应的连接在执行身份验证后保持打开状态。在这种情况下,将此属性设置为 true 的其他请求可以使用该连接而无需重新进行身份验证。
风险在于:
如果用户 A 的连接已通过验证,则用户 B 可以重用 A 的连接;用户 B 的请求根据用户 A 的凭据得到满足。
如果人们了解风险和应用程序doesn't使用模拟,可以使用以下方式配置 HttpClient网络请求处理程序并设置不安全的身份验证连接共享, eg :
HttpClient _client;
public void InitTheClient()
{
var handler=new WebRequestHandler
{
UseDefaultCredentials=true,
UnsafeAuthenticatedConnectionSharing =true
};
_client=new HttpClient(handler);
}
网络请求处理程序doesn't暴露HttpWebRequest.ConnectionGroupName这将允许对连接进行分组,例如按 ID,因此它无法处理模拟。
.NET核心2.1
HttpClient 在 .NET Core 2.1 中被重写,并使用套接字、最小分配、连接池等实现所有 HTTP、网络功能。它还处理NTLM 质询/响应流程分开,因此可以使用相同的套接字连接来服务不同的经过身份验证的请求。
如果有人感兴趣,您可以跟踪从 HttpClient 到 SocketsHttpHanlder 到 HttpConnectionPoolManager 、 HttpConnectionPool、HttpConnection、AuthenticationHelper.NtAuth 的调用,然后返回 HttpConnection 以发送原始字节。