Delphi TNetHTTPRequest / TNetHTTPClient работает на Win 10, но не на Win 7 - PullRequest
0 голосов
/ 08 июня 2018

Новые подробности добавлены под исходным кодом.

Возникла проблема с Delphi, когда интернет-код работает на Win 10, но не на Win 7. Я пытаюсь подключить небольшой проект для их подключения.ком (HIBP).Win 7 возвращает «Ошибка получения сертификата сервера».

Чтобы попытаться исправить проблему Win 7, я добавил OnValidateServerCertificate как в TNetHTTPRequest, так и в TNetHTTPClient.И в Win 10, и в Win 7 OnValidateServerCertificate, похоже, не вызывается.

Я протестировал на 2 компьютерах с Win 10 и 2 компьютерах с Win 7, такие же результаты.1) Почему Win 7 возвращает «Ошибка получения сертификата сервера?2) Почему OnValidateServerCertificate не вызывается на Win 10 или Win 7?

Спасибо за любую помощь!

unit MainUnt;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, 
System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.Net.URLClient, 
System.Net.HttpClientComponent,
  System.Net.HttpClient;

type
  TForm9 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    function HIBPGetRangeResults( const AFirst5CharHashStr: String;
                                  out ARangeResultsStr: String;
                                  out AErrStr: String ): Boolean; inline;
    procedure OnValidateServerCertificate( const Sender: TObject;
                                       const ARequest: TURLRequest;
                                       const Certificate: TCertificate;
                                       var Accepted: Boolean );
  end;

var
  Form9: TForm9;

implementation

{$R *.dfm}

//SHA1( Pa$$word ): 775440A2B268C2F58A9A61B10CC10125703B3015
procedure TForm9.Button1Click(Sender: TObject);
var
  TmpErrStr: String;
  TmpResultsStr: String;
begin
  //HIBP Range wants only the first 5 charactsers so search is anonymous.
  if HIBPGetRangeResults( '77544', TmpResultsStr, TmpErrStr ) then
    ShowMessage( TmpResultsStr )
  else
    ShowMessage( TmpErrStr );
end;

function TForm9.HIBPGetRangeResults( const AFirst5CharHashStr: String;
                                     out ARangeResultsStr, AErrStr: String): 
Boolean;
const
  //GET https://api.pwnedpasswords.com/range/{first 5 hash chars}
  //I don't know of another site at this point that works on Win 10, but 
fails on Win 7.
  kServiceNameStr = 'https://api.pwnedpasswords.com/range/';
var
  TmpNetHTTPRequest: TNetHTTPRequest;
  TmpNetHTTPClient: TNetHTTPClient;
  TmpIHTTPResponse: IHTTPResponse;
begin
  Result := False;
  try
    TmpNetHTTPRequest := TNetHTTPRequest.Create( Nil );
    TmpNetHTTPClient := TNetHTTPClient.Create( Nil );
    try
      TmpNetHTTPClient.OnValidateServerCertificate := 
OnValidateServerCertificate;
      TmpNetHTTPClient.ConnectionTimeout := 3000;
      TmpNetHTTPClient.ResponseTimeout := 3000;
      TmpNetHTTPClient.UserAgent := 'Testing'; //HIBP wants User Agent 
filled.

      TmpNetHTTPRequest.OnValidateServerCertificate := 
OnValidateServerCertificate;
      TmpNetHTTPRequest.ConnectionTimeout := 3000;
      TmpNetHTTPRequest.Client := TmpNetHTTPClient;
      TmpNetHTTPRequest.URL := kServiceNameStr + AFirst5CharHashStr;

      TmpIHTTPResponse := TmpNetHTTPRequest.Execute;
      if TmpIHTTPResponse.StatusCode=200 then
      begin
        ARangeResultsStr := TmpIHTTPResponse.ContentAsString;
        Result := True;
      end
      else
      begin
        AErrStr := 'Result:' + TmpIHTTPResponse.StatusText;
      end;
    finally
      FreeAndNil( TmpNetHTTPClient );
      FreeAndNil( TmpNetHTTPRequest );
    end;
  except on E: Exception do
    AErrStr := E.Message;
  end;
end;

procedure TForm9.OnValidateServerCertificate( const Sender: TObject;
                                              const ARequest: TURLRequest;
                                              const Certificate: 
TCertificate;
                                              var Accepted: Boolean );
begin
  //Just to know it's been called at all.
  //Not called in Win 10 or Win 7.
  Beep;
end;

end.

Ссылка https://api.pwnedpasswords.com/range/55555 (пример первых 5 хеш-символов)) возвращал ошибку сертификата в IE.Я добавил TLS 1.1 и 1.2 в Свойства обозревателя Win 7, Advanced.Это позволило браузеру работать.

Тем не менее программа не работала.Поэтому я обнаружил в Delphi Source (Berlin) «Ошибка получения сертификата сервера», которая привела к «SNetHttpGetServerCertificate».В System.Net.HttpClient:

procedure THTTPClient.DoValidateServerCertificate(LRequest: THTTPRequest);

...

LServerCertificate := DoGetSSLCertificateFromServer(LRequest);
if LServerCertificate.Expiry = 0 then
  raise 
ENetHTTPCertificateException.CreateRes(@SNetHttpGetServerCertificate);

Кажется, что это единственное место, из которого можно сгенерировать это исключение.К сожалению, установка точки останова там (даже при включенных отладочных DCU) никогда не была достигнута.

В TWinHTTPClient.DoExecuteRequest существует возможность ServerCertificateInvalid, которую я пропускаю, проходя через нее.Я не могу сказать с моего компьютера с Win 10, запущен ли он на Win 7.

Кроме того, домен, который я вызываю, похоже, использует очень современную конфигурацию SSL: https://www.ssllabs.com/ssltest/analyze.html?d=api.pwnedpasswords.com&s=104.17.70.67.

Возможно, что-то несовместимо с этим конфигом, Delphi (Berlin) и Win 7?

Спасибо за любую помощь!

Ответы [ 3 ]

0 голосов
/ 03 июля 2018

Та же проблема здесь при доступе https://www.geocaching.com/account/login Работа в Windows 10 без проблем, но получение «Сертификат сервера недействителен или отсутствует» на TNetHTTPClient.Get.

Настройка принята: = True;OnValidateServerCertificate выдаст сообщение «Ошибка при получении сертификата сервера».

Какой обходной путь вы использовали?

0 голосов
/ 03 июля 2018

На самом деле найдено решение, не связанное с Delphi.

От MS:

Приложения и службы, написанные с использованием WinHTTP для соединений SSL, которые используютфлаг WINHTTP_OPTION_SECURE_PROTOCOLS не может использовать протоколы TLS 1.1 или TLS 1.2.Это связано с тем, что определение этого флага не включает эти приложения и службы.

Это обновление добавляет поддержку записи реестра DefaultSecureProtocols, которая позволяет системному администратору указать, какие протоколы SSL следует использовать при использовании флага WINHTTP_OPTION_SECURE_PROTOCOLS..

Это может позволить определенным приложениям, использующим флаг WinHTTP по умолчанию, иметь возможность использовать более новые протоколы TLS 1.2 или TLS 1.1 без необходимости обновлений приложения.

Исправление:

https://support.microsoft.com/en-au/help/3140245/

0 голосов
/ 13 июня 2018

Не удалось получить сертификат haveibeenpwned.com (HIBP) для работы на моих 3 тестовых компьютерах с Win 7.Одна ВМ, 2 физ.

Загруженные данные HIBP и некоторые из них импортированы в качестве теста в Amazon S3 с каждым 5-символьным префиксом в качестве открытого объекта S3.

Теперь тот же код, что и выше, работает только с измененным URL-адресом.

Я до сих пор не знаю, почему «Ошибка получения сертификата сервера» продолжала появляться в Win 7, но нашла приемлемый обходной путь.

Спасибо всем, кто просматривал это!

...