分享

德尔福

 和谐世界 2021-10-06


5 年零 5 个月前
活跃 2 个月前
浏览了 11,000 次
8

我正在尝试在 Delphi Seattle 中使用 TIdHTTP.Get 下载文件。这是一个安卓应用程序,我所有的尝试都失败了。我得到的都是同样的错误“无法加载 SSL 库”。这是程序:

procedure TfrmMain.DownloadPicture(const AURL: string);
var
  MeS: TMemoryStream;
  cidSSL: TIdSSLIOHandlerSocketOpenSSL;
  cidHTTP: TIdHTTP;
begin
  cidHTTP:= TIdHTTP.Create(nil);
  cidSSL:= TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  Mes := TMemoryStream.Create;

  try
    cidHTTP.ReadTimeout := 30000;
    cidHTTP.IOHandler := IdSSL;
    cidSSL.SSLOptions.Method := sslvSSLv3;
    cidSSL.SSLOptions.Mode := sslmUnassigned;
    cidSSL.StartSSL;
    cidHTTP.Get(AURL, Mes);
  except
    on E : Exception do
      begin showmessage('Error: '+E.Message);
      end;
  end;
  Mes.Position := 0;
  frmImage.Image.Bitmap.LoadFromStream(Mes);
end;
2016 年 5 月 8 日 22:43
词儿莫尔
30511个金徽章44银徽章1313枚铜牌
17

如果您没有使用 Android 6 Marshmallow,OpenSSL 应该可以在 Android 上正常工作。当你得到“could not load”错误时,你可以WhichFailedToLoad()IdSSLOpenSSLHeaders单元中调用Indy的函数来找出OpenSSL无法加载的原因。如果你的设备没有预装 OpenSSL,你可以用你的应用程序部署 OpenSSL 二进制文件,并使用 Indy 的IdOpenSSLSetLibPath()函数告诉 Indy 从哪里加载它们。

也就是说,从 Android 6 Marshmallow 开始,Google 不再支持Android 上的OpenSSL它已被名为BoringSSL的自定义分支所取代,但Indy 尚不完全支持分支(尽管在西雅图发布后对 Indy 进行了一些与 BoringSSL 相关的更改)。因此,如果您在 Android 6 上使用 Indy SSL/TLS 时遇到问题,您可以尝试升级到最新的Github 快照,看看是否有帮助。

BoringSSL对 OpenSSL API 接口进行了一些重大更改(删除函数、更改数据类型等),因此它无法向后兼容现有的 OpenSSL 代码。但更糟糕的是,BoringSSL 使用与 OpenSSL 相同的库文件名,并在设备启动时预加载,因此无法在您的 Android 应用程序中部署自定义构建的 OpenSSL 库二进制文件。当应用程序尝试在运行时加载 OpenSSL 库文件名时,Android 将简单地使用预加载的 BoringSSL 二进制文件(无论您是否调用 Indy 的IdOpenSSLSetLibPath()函数)。

Indy 在 Android 的 NDK 级别运行,而不是 Java 级别,因此要使 Indy 避免 BoringSSL 需要用户:

  1. 使用与 BoringSSL 不冲突的新文件名重新编译 OpenSSL 库(AFAIK 没有可用的已知版本),然后更新 Indy 以使用这些文件名。

  2. 将 OpenSSL 源代码直接编译到他们的 Android 应用程序中。Indy 目前没有设置为支持除 iOS 以外的任何平台上的 OpenSSL 静态链接,但是IdSSLOpenSSLHeaders_static如果有人可以.a为 Android的 OpenSSL生成可行的文件,那么这应该是一个小的更改,以使用相关定义更新 Indy 的单元我知道至少有一个用户尝试这条路线,但该用户还没有成功(获取源代码完全正确链接的错误)。

  3. 切换到 Android 的更高级别的基于 Java 的加密 API。这是 Google 的首选解决方案。但 Indy 目前不支持。这样做需要编写一套全新的TIdStack,并TIdIOHandler为Android类插座I / O和SSL / TLS,用来访问的Java API JNI调用。但这有需要处理的性能和线程问题。

因此,目前没有已知可行的解决方法可以使 Indy SSL/TLS 在 Android 6+ 上运行。


更新:Embarcadero 论坛中的用户能够找到.so与 Indy 兼容并在 Android 6 上运行的OpenSSL文件:

https://forums./thread.jspa?threadID=211089

在多次报告我的应用程序如果安装在 Android 6 设备上会崩溃后,我在网上搜索了一些提示和几个需要的 .so 编译文件,1.02 版本,将这两个文件添加到我的应用程序的 Play 商店部署中(资产\内部)并更改了 Indy 的路径调用

IdOpenSSLSetLibPath(TPath.GetDocumentsPath)

在我的数据模块的 OnCreate 中。

在对我的代码进行这些修改后,我的应用程序可以在我的全新 S7 和 Android 6.0.1 以及所有其他最近的 Android 设备上完美运行(使用 Play 商店部署进行测试)。

现在弹出谷歌警告,告诉我与我的应用程序一起部署的 OpsnSSL 文件不是最低要求的 1.02f 版本(或 1.01r)......所以我在这个论坛上发帖。

...

无论如何,您可以在此处下载最新的 .so 文件,即我此时部署的文件:https : //drive.google.com/file/d/0B7AxqW32K0oXWW9nUk9qaFpHT0k/view?usp=sharing

同一讨论中的另一位用户似乎也取得了一些成功:

几个月来,我一直在 android 6 上运行加载 .so 库。新问题是我们需要编译新版本的 openssl 库。Cygwin 无法正常为我编译,所以我切换到 linux 安装来创建它们(如果可能)https://wiki./index.php/Android#Build_the_OpenSSL_Library_2

这是一个存储库,您可以获取一些当前预构建的存储库https://github.com/emileb/OpenSSL-for-Android-Prebuilt.git


更新:以下(德语)论坛讨论为注册用户提供适用于 Android(和 iOS 模拟器)的 OpenSSL 1.0.2g 二进制文件。它们不会在 Google Play 商店中显示安全警告:

http://www./188736-kompilierte-openssl-bibliotheken-fuer-android.html

OpenSSL 1.0.2g Android.zip

OpenSSL 1.0.2g iOS 模拟器.zip


更新:适用于 OpenSSL 1.0.2g 的 Android 二进制文件现已在 Embarcadero 附件论坛中提供:

https://forums./thread.jspa?threadID=211147

然后,要加载 OpenSSL 而不是 BoringSSL,请按照下列步骤操作:

  1. 将这 2 个.so文件添加到您的项目部署中并将它们设置为部署到.\assets\internal\文件夹

  2. 将该System.StartupCopy单位添加为 DPRuses条款中一个单位

  3. IdOpenSSLSetLibPath(TPath.GetDocumentsPath)在应用程序启动时调用


更新:OpenSSL 1.0.1t 和 1.0.2h 二进制文件现在位于 Embarcadero 附件论坛中:

https://forums./thread.jspa?threadID=211147


更新:二进制文件现已发布在 Indy 的 Fulgan 镜像上:

http://indy./SSL/


更新:Indy 不再使用 Fulgan 镜像来托管 OpenSSL 二进制文件。他们现在在自己的 GitHub 存储库中:

https://www./2020/06/16/openssl-binaries-moved-to-github/

https://github.com/IndySockets/OpenSSL-Binaries

2016 年5 月 9 日 18:17回答
雷米勒博
473k2929金徽章379379银徽章645645青铜徽章
  • 1
    谢谢雷米!我正在使用 Android 6 Marshmallow。到现在为止,我不得不为我的问题找出另一种解决方案并奏效,但我肯定将来会再次面临这个问题,您的回答很有帮助。
    —— 词儿莫尔
    2016 年 5 月 10 日 1:55
  • 我很伤心,我很生气,我很绝望。我讨厌谷歌这样做。我讨厌 Embarcadero 没有选择在 Android 6 中使用 SSL/TLS(这是今天的死刑判决......没有网络加密的应用程序?你好?)。我一直在努力使用 Delphi 的原因之一。总是这么大的问题。另一方面,我有点理解 Google 决定让一切都通过他们的操作系统的决定背后的要点。Delphi 总是很特别(不是原生的,等等)。更让我高兴的是,有像 Remy 这样的乐于助人的人和发现这些文件的人。至少谷歌正确地调用了他们的分支:BoringSSL。
    —— 斯坦
    2017 年 2 月 25 日 13:59
  • 多年后来到这里。正如 Remy 提到的,您需要下载 so 文件。下载后转到 Project -->Deployment 并添加那些 so 文件。编辑远程路径。你完成了! 8 月 2 日 14:12
1

只需将 TidHTTP 组件换成 TNetHTTPClient

19 年 8 月 29 日 18:29 回答
用户5467230
2111个青铜徽章
  • 当他已经接受了已经获得大量赞成票的非常详细的答案时,这对海报有什么帮助? 2019-08-29 19:29
  • 1
    你甚至不必非常聪明就能理解它是如何帮助的。但我会尽量解释,就好像我在和孩子说话一样。您删除有问题的组件并取而代之,保留插入新组件的所有属性,无需下载,无需外部文件。如果你有一块新玻璃,你为什么要把碎玻璃的碎片粘在一起?
    —— 用户5467230
    2019 年 8 月 30 日 20:14
0

可能您有一个新的 OpenSSL 库和一个较旧的 Indy 版本。检查这个: Indy 10 - IdSMTP.Connect 引发“无法加载 SSL 库”。

社区机器人
111个银徽章
2016 年5 月 9 日 1:28回答
亚历山大·M
9991010银徽章1919枚铜牌
  • Alexandre,我使用的是 Delphi Seattle,Indy 版本是 10.6.2.5298。尽管如此,这些步骤仍然适用于 Windows。
    —— 词儿莫尔
    2016 年 5 月 9 日 3:02
  • 只有一个 Indy 源代码。旧版本的 Indy 不支持新的 OpenSSL,与平台无关。 2016 年 6 月 18 日 8:00
0

有 32/64 位版本。确保您拥有正确版本的文件。

请参阅此 FTP以获取正确版本。

下载二进制文件的其他镜像在这里

2016 年5 月 9 日 11:04回答
Germán Estévez -Neftalí-
5,8121717银徽章3131枚铜牌
0

我使用此代码,这有效:

  procedure TfPrecos.GetImageByUrl(URL: string);
  var
    Strm: TMemoryStream;
    vIdHTTP: TIdHTTP;
    cidSSL: TIdSSLIOHandlerSocketOpenSSL;
  begin
  IdOpenSSLSetLibPath(TPath.GetDocumentsPath);  //libcrypto.so and libssl.so in ./assets/internal
    vIdHTTP.IOHandler := cidSSL;
    cidSSL.SSLOptions.Method := sslvSSLv23; // version 2.3
    cidSSL.SSLOptions.Mode := sslmUnassigned;
    cidSSL.StartSSL;
    try
      vIdHTTP.Get(URL, Strm);
      if (Strm.Size > 0) then
      begin
        Strm.Position := 0;
        try
          Image1.Bitmap.LoadFromStream(Strm);
        finally
       
        end;
      end;
    finally
      Strm.DisposeOf;
      vIdHTTP.DisposeOf;
    end;

  end;

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多