错误“无法加载 SSL 库"在 Android 上使用 TidHTTP [英] Error "Could not load SSL library" on Android with TidHTTP

查看:29
本文介绍了错误“无法加载 SSL 库"在 Android 上使用 TidHTTP的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to download a file with TIdHTTP.Get in Delphi Seattle. It's an app for android and all my attempts fails. All i get it's the same error "Could not load SSL library". This is the procedure:

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;

推荐答案

如果您使用 Android 6 Marshmallow,OpenSSL 应该可以在 Android 上正常工作.当您收到无法加载"时错误,您可以在 IdSSLOpenSSLHeaders 单元中调用 Indy 的 WhichFailedToLoad() 函数以找出无法加载 OpenSSL 的原因.如果您的设备没有预装 OpenSSL,您可以在您的应用中部署 OpenSSL 二进制文件,并使用 Indy 的 IdOpenSSLSetLibPath() 函数告诉 Indy 从何处加载它们.

If you are NOT using Android 6 Marshmallow, OpenSSL should be working fine on Android. When you get the "could not load" error, you can call Indy's WhichFailedToLoad() function in the IdSSLOpenSSLHeaders unit to find out why OpenSSL could not be loaded. If your device does not have OpenSSL pre-installed, you can deploy the OpenSSL binaries with your app, and use Indy's IdOpenSSLSetLibPath() function to tell Indy where to load them from.

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

That being said, starting with Android 6 Marshmallow, Google no longer supports OpenSSL on Android. It has been replaced with a custom fork named BoringSSL, which Indy does not fully support yet (although some BoringSSL-related changes have been made to Indy after Seattle's release). So, if you are having trouble with using Indy SSL/TLS on Android 6, you can try upgrading to the latest Github snapshot to see if it helps.

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

BoringSSL makes some major changes to the OpenSSL API interface (dropping functions, changing data types, etc), so it is not backwards-compatible with existing OpenSSL code. But to make matters worse, BoringSSL uses the same library filenames as OpenSSL, and is pre-loaded at device startup, so it is not possible to deploy custom-built OpenSSL library binaries with your Android app. Android will simply use the pre-loaded BoringSSL binaries when the app tries to load the OpenSSL library filenames at runtime (regardless of whether you call Indy's IdOpenSSLSetLibPath() function).

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

Indy operates at the NDK level of Android, not the Java level, so to make Indy avoid BoringSSL would require users to either:

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

  1. recompile the OpenSSL libraries with new filenames that don't conflict with BoringSSL (AFAIK no known version of this is available), and then update Indy to use those filenames.

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

compile the OpenSSL source code directly into their Android app. Indy is not currently setup to support static-linking of OpenSSL on any platform other than iOS, but this should be a minor change to update Indy's IdSSLOpenSSLHeaders_static unit with the relevant definitions if someone can produce viable .a files for OpenSSL on Android. I do know of at least one user attempting this route, but that user has not had success yet (errors getting the source code to fully link correctly).

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

switch to Android's higher-level Java-based crypto APIs. This is Google's preferred solution. But Indy does not support it at this time. Doing so would require writing a whole new set of TIdStack and TIdIOHandler classes for Android socket I/O and SSL/TLS, using JNI calls to access the Java APIs. But this has performance and threading issues that need to be dealt with.

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

So, there is no known viable workaround available at this time to make Indy SSL/TLS work on Android 6+.

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

Update: a user in the Embarcadero forums was able to find OpenSSL .so files that are compatible with Indy and work on Android 6:

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

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

After many reports of my apps crashing if installed in Android 6 devices I've searched the net for some tips and the couple of needed .so compiled files, 1.02 version, added the two files to the play store deployment of my apps (assetsinternal) and changed the Indy's path calling

IdOpenSSLSetLibPath(TPath.GetDocumentsPath)

IdOpenSSLSetLibPath(TPath.GetDocumentsPath)

在我的数据模块的 OnCreate 中.

in the OnCreate of my datamodule.

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

After those modifications of my code my Apps run perfectly on my brand new S7 with Android 6.0.1, and on all the other recent Android devices (tested using the Play Store deployment).

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

And now the Google warning pops up telling me that the OpsnSSL files deployed with my apps are not of the minimum required 1.02f version (or 1.01r).... and so my post in this forum.

...

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

Anyway you can download here the latest .so files, the ones that I deploy at this moment: https://drive.google.com/file/d/0B7AxqW32K0oXWW9nUk9qaFpHT0k/view?usp=sharing

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

Another user in the same discussion also seems to have some success as well:

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

Ive been running on android 6 loading the .so libraries just fine for months. The new problem is we need to compile new versions of the openssl libraries. Cygwin is not working correctly to compile for me so im switching to a linux install to create them (if possible) https://wiki.openssl.org/index.php/Android#Build_the_OpenSSL_Library_2

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

heres a repository you can grab some current prebuilt ones https://github.com/emileb/OpenSSL-for-Android-Prebuilt.git


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


Update: The following (German) forum discussion provides OpenSSL 1.0.2g binaries for Android (and iOS Simulator) to registered users. They do not display the security warning in the Google Play store:

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

OpenSSL1.0.2g 安卓.zip

OpenSSL 1.0.2g iOS 模拟器.zip

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

Update: the Android binaries for OpenSSL 1.0.2g are now available in the Embarcadero Attachments forum:

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

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

Then, to load OpenSSL instead of BoringSSL, follow these steps:

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

  1. Add the 2 .so files to your project deployment and set them to deploy to the .assetsinternal folder

添加 System.StartupCopy 单元作为 DPR uses 子句中的第一个单元.

add the System.StartupCopy unit as the first unit in your DPR's uses clause.

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


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


Update: OpenSSL 1.0.1t and 1.0.2h binaries are now in the Embarcadero Attachments forum:

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

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

Update: the binaries have now been posted on Indy's Fulgan mirror:

http://indy.fulgan.com/SSL/

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

Update: Indy is no longer using the Fulgan mirror for hosting OpenSSL binaries. They are now in their own GitHub repo:

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

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

这篇关于错误“无法加载 SSL 库"在 Android 上使用 TidHTTP的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆