Определение версии TLS, используемой для вызовов HttpClient POST или GET - PullRequest
0 голосов
/ 07 января 2019

Я пытаюсь получить информацию о версии TLS. Приведенный ниже код делает успешный вызов HTTP GET с использованием HttpClient. Что мне не хватает? Где я могу получить информацию о версии TLS от HttpClient?

Я делаю то же самое, что было предложено в Какая версия TLS была согласована? , но это относится к WebRequest, который отличается от HttpClient.

static async Task MainAsync()
{
    Uri baseURI = new Uri("https://jsonplaceholder.typicode.com/posts/1");
    string apiPath = "";
    using (var client = new HttpClient())
    {
        client.BaseAddress = baseURI;
        HttpResponseMessage response = await client.GetAsync(apiPath);
        Console.WriteLine("HTTP status code: " + response.StatusCode.ToString());
        GetSSLConnectionInfo(response, client.BaseAddress.ToString(), apiPath);
    }
    Console.ReadKey();
}

static async Task GetSSLConnectionInfo(HttpResponseMessage response, string baseURI, string apiPath)
{
    using (Stream stream = await response.RequestMessage.Content.ReadAsStreamAsync())
    {
        BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic;
        Stream CompressedStream = null;
        if (stream.GetType().BaseType == typeof(GZipStream))
        {
            CompressedStream = (GZipStream)stream;
        }
        else if (stream.GetType().BaseType == typeof(DeflateStream))
        {
            CompressedStream = (DeflateStream)stream;
        }

        var objbaseStream = CompressedStream?.GetType().GetProperty("BaseStream").GetValue(stream);
        if (objbaseStream == null)
        {
            objbaseStream = stream;
        }

        var objConnection = objbaseStream.GetType().GetField("m_Connection", bindingFlags).GetValue(objbaseStream);
        var objTlsStream = objConnection.GetType().GetProperty("NetworkStream", bindingFlags).GetValue(objConnection);
        var objSslState = objTlsStream.GetType().GetField("m_Worker", bindingFlags).GetValue(objTlsStream);
        SslProtocols b = (SslProtocols)objSslState.GetType().GetProperty("SslProtocol", bindingFlags).GetValue(objSslState);
        Console.WriteLine("SSL Protocol Used for " + baseURI + apiPath + System.Environment.NewLine + "The TLS version used is " + b);
    }
}

Я ожидаю информацию о соединении TLS, но получаю исключение.

Ответы [ 2 ]

0 голосов
/ 08 января 2019

Под капотом HttpClient используется внутренний класс TlsStream (как в вашем примере для WebRequest). Нам просто нужно найти его в другом месте. Вот пример:

static void Main(string[] args)
{
    using (var client = new HttpClient())
    {
        using (var response = client.GetAsync("https://example.com/").Result)
        {
            if (response.Content is StreamContent)
            {
                var webExceptionWrapperStream = GetPrivateField(response.Content, "content");
                var connectStream = GetBasePrivateField(webExceptionWrapperStream, "innerStream");
                var connection = GetPrivateProperty(connectStream, "Connection");
                var tlsStream = GetPrivateProperty(connection, "NetworkStream");
                var state = GetPrivateField(tlsStream, "m_Worker");
                var protocol = (SslProtocols)GetPrivateProperty(state, "SslProtocol");
                Console.WriteLine(protocol);
            }
            else
            {
                // not sure if this is possible
            }
        }
    }
}

private static object GetPrivateProperty(object obj, string property)
{
    return obj.GetType().GetProperty(property, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}

private static object GetPrivateField(object obj, string field)
{
    return obj.GetType().GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}

private static object GetBasePrivateField(object obj, string field)
{
    return obj.GetType().BaseType.GetField(field, BindingFlags.Instance | BindingFlags.NonPublic).GetValue(obj);
}
0 голосов
/ 07 января 2019

Вы можете легко извлечь сертификат, используя ServerCertificateCustomValidationCallback

Uri baseURI = new Uri("https://jsonplaceholder.typicode.com/posts/1");
string apiPath = "";
using (var client = new HttpClient(new HttpClientHandler
{
    ServerCertificateCustomValidationCallback = (message, certificate2, arg3, arg4) =>
    {
        Console.WriteLine(certificate2.GetNameInfo(X509NameType.SimpleName, false));
        return true;
    }
}))
{
    client.BaseAddress = baseURI;
    HttpResponseMessage response = await client.GetAsync(apiPath);
    Console.WriteLine("HTTP status code: " + response.StatusCode.ToString());
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...