Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Когда клиент и сервер согласовывают подключение HTTPS, сначала необходимо установить подключение TLS. В рамках рукопожатия TLS клиент отправляет доменное имя сервера, к которому он подключается, в одном из расширений TLS. При размещении нескольких (виртуальных) серверов на одном компьютере эта функция протокола TLS позволяет клиентам различать, к каким из этих серверов они подключаются и настраивают параметры TLS, например сертификат сервера, соответственно.
При выполнении HTTP-запроса HttpClient реализация автоматически выбирает значение расширения имени сервера (SNI) на основе URL-адреса, к которому подключается клиент. Для сценариев, требующих более ручного управления расширением, можно использовать один из следующих подходов.
Заголовок хоста
Заголовок HTTP узла выполняет аналогичную функцию в качестве расширения SNI в TLS. Он позволяет целевому серверу различать запросы для нескольких имен узлов в одном IP-адресе.
HttpClient автоматически заполняет заголовок узла с помощью URI запроса. Однако можно также задать его значение вручную, а HttpClient также использовать новое значение в расширении SNI. Вы можете использовать либо HttpRequestMessage.Headers.Host, либо HttpClient.DefaultRequestHeaders.Host, чтобы достичь этого эффекта.
using HttpClient client = new();
client.DefaultRequestHeaders.Host = "www.microsoft.com";
using var response = await client.GetAsync("https://127.0.0.1:5001/");
System.Console.WriteLine(response);
Замечание
Этот метод не позволяет избежать отправки SNI в целом при подключении к URL-адресу с именем узла. Если для заголовка задана пустая строка, HttpClient вместо этого используется имя узла из URL-адреса.
Замечание
Настройка заголовка 'Host' влияет на проверку сертификата сервера. По умолчанию клиент ожидает, что сертификат сервера соответствует имени узла в заголовке узла.
Проверка подлинности SslStream вручную через ConnectCallback
Более сложный, но и более мощный вариант — использовать SocketsHttpHandler.ConnectCallback. Начиная с .NET 7, можно вернуть прошедший SslStream проверку подлинности и таким образом настроить, как устанавливается TLS-подключение. В обратном вызове произвольные SslClientAuthenticationOptions параметры можно использовать для аутентификации на стороне клиента.
var handler = new SocketsHttpHandler
{
ConnectCallback = async (context, cancellationToken) =>
{
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp) { NoDelay = true };
try
{
await socket.ConnectAsync(context.DnsEndPoint, cancellationToken);
var sslStream = new SslStream(new NetworkStream(socket, ownsSocket: true));
// When using HTTP/2, you must also keep in mind to set options like ApplicationProtocols
await sslStream.AuthenticateAsClientAsync(new SslClientAuthenticationOptions
{
TargetHost = context.DnsEndPoint.Host,
}, cancellationToken);
return sslStream;
}
catch
{
socket.Dispose();
throw;
}
}
};
using HttpClient client = new(handler);
using var response = await client.GetAsync("https://www.microsoft.com");
System.Console.WriteLine(response);