【问题标题】:Delphi - SSL TCP communication with Indy componentsDelphi - 与 Indy 组件的 SSL TCP 通信
【发布时间】:2012-08-04 09:20:21
【问题描述】:

我在 Delphi XE2 中使用 TIdSSLIOHandlerSocketOpenSSL Indy 组件通过 TCP 将数据发送到 SSL 服务器(Apple Push Notification Service)。我已经让它在一定程度上起作用,但不确定我是否会以最好的方式去做。我正在做以下事情:

  • 设置 SSL 属性公司。证书路径
  • 调用.Open方法打开连接
  • 检查 OnStatusInfoEx 事件中的 AType 参数,直到我得到“握手完成”
  • 使用 .WriteDirect 发送数据
  • 使用 .Close 关闭连接

有没有更好的方法来知道连接何时准备好发送数据?有人有直接通过 TCP 使用 TIdSSLIOHandlerSocketOpenSSL 组件的示例代码吗?我发现的示例主要用于 HTTP 调用,其中仅附加了 TIdSSLIOHandlerSocketOpenSSL 组件以保护连接。

【问题讨论】:

  • Indy 组件方法是阻塞的,不需要等待连接握手。将 TIdSSLIOHandlerSocketOpenSSL 分配给 IdTCPClient 的 IOHandler 属性。然后调用 IOHandler 的 Connect 方法(这会阻塞直到安全连接建立),然后发送数据。

标签: delphi ssl tcp openssl indy


【解决方案1】:

由于您使用的是客户端组件,因此如果服务器要对客户端的证书进行身份验证,则只需在客户端上设置证书即可。

否则,将 TIdSSLIOHandlerSocketOpenSSL 的 SSLOptions.Mode 设置为 sslmClient,应该可以连接。

最好启用 VerifyMode 并使用套接字组件上的 OnVerifyPeer 事件来验证服务器证书上的指纹,以避免中间人攻击。

根据您的 Indy 版本,您可能需要将 SSLOptions Method 设置为 sslvTLSv1。一些 Web 服务器不再支持 SSLv2,Indy 9 默认支持。

下面是一些示例代码,演示如何使用 TCP 组件通过 SSL 检索网页:

procedure TForm1.Button1Click(Sender: TObject);
var
  s: String;
begin
  IdTCPClient1.Host := 'example.com';
  IdTCPClient1.Port := 443;
  IdTCPClient1.Connect;
  IdTCPClient1.WriteLn('GET / HTTP/1.1');
  IdTCPClient1.WriteLn('Host: example.com');
  IdTCPClient1.WriteLn('');
  // Retrieve all the data until the server closes the connection
  s := IdTCPClient1.AllData;
  Memo1.Lines.Add(s);
end;

不要忘记将 OpenSSL 库 libeay32.sllssleay32.dll 包含在与 Windows 上的 EXE 相同的文件夹中。使用 Indy 10 的标准(最新)二进制文件。

【讨论】:

  • 非常感谢马库斯让我走上了正轨,比我做的更干净。是的,服务器将在客户端验证证书。我正在使用服务器似乎很满意的 SSLOptions Method sslvSSLv3。
  • Indy 有一个 TIdHTTP 组件,它支持 HTTP 和 HTTPS url(您仍然需要分配 SSL IOHandler 才能使用 HTTPS),例如:s := IdHTTP1.Get('https://example.com/'); 直接使用 TIdTCPClient 不是对具有所有复杂性的 HTTP 来说是个好主意,使用 AllData 绝对是与 HTTP 一起使用的错误。
【解决方案2】:

这对我有用。我正在使用 Delphi 2010,但这可能在 Delphi XE2 上也同样有效(未经测试)。我使用的是 Indy 当前的最新版本,即 4774 版,而不是开箱即用的版本。

我在一个数据模块或网络模块上有 3 个组件:

  1. TIdHTTP
  2. TIdSSLIOHandlerSocketOpenSSL
  3. TidCookieManager

在设计时将所有组件相互挂钩,在运行时进行以下更改:如果协议是纯 http:,则断开 TIdSSLIOHandlerSocketOpenSSL 组件。如果协议为 https:,则将 IdHTTP 的 Handler 属性设置为 IdSSLIOHandlerSocketOpenSSL。

在 SSL 选项中,将方法设置为 sslvSSLv23,将 SSLVersions 设置为 [sslvSSLv2,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2]。我发现这些属性的其他排列不起作用。我无法解释。我只知道这适用于各种网络服务器。

从那里开始很容易。要获取 GET,只需调用 TIdHTTP 上的 Get() 方法。对于 POST,调用 Post()。参数和 Cookie 可以通过明显命名的属性访问。

我在让开箱即用的版本正确 POST 时遇到了很多麻烦,但有了尖端修订版,并设置了我提到的选项,它变得轻而易举。

【讨论】:

  • 组件的IOHandler不需要修改。当您分配 TIdSSLIOHandlerSocketOpenSSL 时,Indy 在使用它之前会自动检查协议是否为 HTTPS。此外,OP 没有使用 TIdHTTP。
  • sslvSSLv23 是一个特殊值 - 与 SSLVersions 互斥 - 您可以设置一个或另一个,无需同时设置。 SSLOptions 是较旧的方法,在最近的 Indy 版本中,SSLVersions 是首选方法。您不需要使用 sslvSSLv2,因为它已过时且不应再使用,因此只能使用版本 3 及更高版本。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-01-27
  • 2017-02-15
  • 2012-05-04
  • 2017-03-03
  • 2011-12-21
  • 2012-02-28
  • 2016-07-02
相关资源
最近更新 更多