【问题标题】:Delphi TNetHTTPRequest/TNetHTTPClient Works on Win 10, but not Win 7Delphi TNetHTTPRequest/TNetHTTPClient 适用于 Win 10,但不适用于 Win 7
【发布时间】:2018-11-18 19:12:15
【问题描述】:

在源代码下方添加了新的细节。

有一个问题是 Delphi,其中 Internet 代码在 Win 10 上工作,但在 Win 7 上不工作。我正在尝试将一个小项目连接到 haveibeenpwned.com (HIBP)。 Win 7 返回“获取服务器证书时出错。”

为了尝试修复 Win 7 问题,我向 TNetHTTPRequest 和 TNetHTTPClient 添加了 OnValidateServerCertificate。在 Win 10 和 Win 7 中,似乎都没有调用 OnValidateServerCertificate。

我在 2 台 Win 10 计算机和 2 台 Win 7 计算机上进行了测试,结果相同。 1) 为什么 Win 7 返回“获取服务器证书时出错? 2) 为什么在 Win 10 或 Win 7 上不调用 OnValidateServerCertificate?

感谢您的帮助!

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 中返回证书错误。我在 Win 7 Internet Options, Advanced 中添加了 TLS 1.1 和 1.2。这允许浏览器工作。

程序仍然没有运行。所以我找到了导致“SNetHttpGetServerCertificate”的 Delphi Source (Berlin) “Error getting Server Certificate”。在 System.Net.HttpClient 中:

procedure THTTPClient.DoValidateServerCertificate(LRequest: THTTPRequest);

...

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

这似乎是唯一可以引发此异常的地方。不幸的是,在那里设置断点(即使打开了调试 DCU)也没有被命中。

存在 ServerCertificateInvalid 的可能性 TWinHTTPClient.DoExecuteRequest 我通过时经过。我无法从我的 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 不兼容?

感谢您的帮助!

【问题讨论】:

    标签: delphi windows-7 ssl-certificate


    【解决方案1】:

    其实找到了解决办法,与Delphi无关。

    来自 MS:

    使用 WinHTTP for Secure 编写的应用程序和服务 套接字层 (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/

    【讨论】:

    • 我从更新目录中添加了更新,它已经安装了。从support.microsoft.com/en-au/help/3140245/… 安装 Easy Fix 下载解决了该问题。不幸的是,让我的用户都安装 Easy Fix 是不切实际的。所以实际上,为了避免这种情况,我转向了 Amazon S3。然而,2borG 为其他服务找到了一个很好的解决方案,所以我赞成它并将其作为首选答案。
    • 如果必须部署它,可以放置上面链接中所需的注册表项。当我说 Easy Fix 不可行时,我没有考虑到这一点。
    【解决方案2】:

    无法让 haveibeenpwned.com (HIBP) 证书在我的 3 Win 7 测试计算机上工作。一台虚拟机,两台物理机。

    下载 HIBP 数据并将其中的一些数据作为测试导入到 Amazon S3,每个 5 个字符的前缀作为 S3 公共对象。

    现在与上面相同的代码只改变了 url。

    我仍然不知道为什么“获取服务器证书时出错”一直出现在 Win 7 上,但找到了可以接受的解决方法。

    感谢所有查看此内容的人!

    【讨论】:

      【解决方案3】:

      同样的问题在这里访问https://www.geocaching.com/account/login 在 Windows 10 中工作没有问题,但在 TNetHTTPClient.Get 上得到“服务器证书无效或不存在”。

      接受的设置:= True; OnValidateServerCertificate 将给出“获取服务器证书时出错”。

      您使用了什么解决方法?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-11-06
        • 1970-01-01
        • 2013-02-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多