【问题标题】:Indy 10 and OpenSSLIndy 10 和 OpenSSL
【发布时间】:2013-04-28 09:13:22
【问题描述】:

我最近将我的 Delphi 7 升级到了 Delphi XE2,我对它有点陌生。我使用带有 OpenSSL 的 Indy 10 来接收 HTTP 内容。它工作得很好,我想与其他人分享我的程序。我刚刚发现如果没有 OpenSSL 库,我的程序将无法在其他 PC 上运行。我什至没有收到丢失 DLL 文件的异常、错误等。我认为 Indy10 要么具有原生 SSL 支持,要么至少在编译后使用资源中的 DLL,因此它是可移植的。我有两个问题:

1) 我如何让用户知道他/她缺少 OpenSSL 库? (我的朋友在没有 OpenSSL DLL 的情况下没有报告异常、错误等。)

2) 是否可以让 Indy10 从资源中读取 OpenSSL 库?

【问题讨论】:

    标签: delphi ssl delphi-xe2 indy indy10


    【解决方案1】:

    Indy 本身并不实现 SSL。它所做的是实现了一个灵活的 IOHandler 架构,允许将任何 SSL 实现插入 Indy。 Indy 本身实现了自己的基于 OpenSSL 的 IOHandler 类(计划在未来提供 MS CryptoAPI 支持)。例如,SecureBlackbox 为其自己的 SSL 引擎提供了一个 Indy IOHandler 类。

    在大多数平台上,OpenSSL 通过外部 DLL 使用,不能从资源中使用。 Indy 不附带 OpenSSL DLL,因为 OpenSSL 加密受到国际进出口法律的限制,所以要么在国际上发布的操作系统供应商有特殊的许可证来发布 OpenSSL DLL,要么最终用户必须自己在本地下载/编译 OpenSSL。这就是让 Indy 在 OpenSSL 方面“可移植”的原因 - Indy 使用预先安装在 Indy 之外的任何 OpenSSL DLL,无论是在操作系统中还是在您的应用程序自己的安装文件夹中。

    与 Indy 相关的唯一例外是 iOS 上的 OpenSSL,它要求静态使用 OpenSSL,因为 iOS 设备上不允许使用第三方动态库。

    如果你想在其他平台上静态使用 OpenSSL 和 Indy,你必须自己编译/获取 OpenSSL 的静态版本并将其添加到你的项目中,然后重新编译 Indy 以启用其STATICLOAD_OPENSSL 定义(目前仅为 iOS 定义),最后在代码的 uses 子句中包含 IdSSLOpenSSLHeaders_static.pas 单元以连接必要的支持代码。 请注意,这仅在最近发布的 Indy 10.6 版本中受支持。

    如果这对您来说工作量太大,那么请使用与 Indy 兼容的第三方 SSL 实现,例如 SecureBlackbox,或者编写您自己的 IOHandler 类来满足您的需求。

    至于你的其他问题:

    1) 如果 Indy 在套接字操作期间无法正确加载 OpenSSL,确实会引发异常。因此,这些异常很可能在您有机会向用户报告之前就被捕获并吞下。如果您不想依赖它,那么您可以在开始套接字工作之前在 IdSSLOpenSSLHeaders.pas 单元中手动调用 Indy 的 Load() 函数。 Load() 会将 OpenSSL 加载到内存中(如果尚未加载)。如果Load() 失败,您可以在同一单元中调用WhichFailedToLoad() 函数来找出Load() 失败的原因。

    2) 不,不可能从资源中使用 OpenSSL(没有一些非常严重的低级技巧)。

    【讨论】:

    • 为什么 Indy 不原生实现 SSL?每个人都因为需要这些外部 dll 而受苦。
    • 本地实现 SSL 将是一项重大任务。当其他人已经提供了实现时,为什么还要浪费时间和精力呢?无论如何,我确实提到我们计划为 CryptoAPI 创建一个 IOHandler 包装器,以便解决 Windows 上的 DLL 和导入/导出问题,因为它内置于操作系统中。在其他平台上,常用的是OpenSSL。
    • 其他流行的库,如 ICS 和 Synapse,也没有原生实现 SSL。他们依赖于 OpenSSL 等外部库。
    • @Remy Indy 是否实现了 CryptoAPI 的包装器?
    • @NasreddineGalfout 不,还没有。它仍然在todo list
    【解决方案2】:

    1) 尝试在调用 Indy 之前自己加载 e DLL,如果 LoadLibrary 失败,您可以引发异常。

    2) 你可以,看这个:

    Load a DLL From a Resource Directly From Memory in Delphi Applications

    【讨论】:

    • 这应该可以,但我将不得不编辑实际的 Indy SourceCode,而且我不知道从哪里开始。
    • 为什么要编辑 Indy Code?应用程序只会加载一次dll,所以如果你在调用indy之前加载它,你会没事的。
    • 我不知道这是否可能,如果 Indy 在我做之前已经调用了 LoadLibrary 怎么办(初始化)。如果 Indy 调用 GetModuleHandle 等会怎样。它可能会加载库两次或其他什么。还没有测试任何东西,但我稍后会测试它是否有效。
    • BTMemoryModule 中的 BTMemoryLoadLibary 是否真的将模块添加到进程的已加载模块列表中?
    • Indy 在需要之前不会将 OpenSSL DLL 加载到内存中。 Indy 不使用GetModuleHandle(),它通过LoadLibrary() 加载DLL 并跟踪这些句柄,在不再需要它们时关闭它们。
    猜你喜欢
    • 1970-01-01
    • 2020-02-04
    • 2011-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-21
    相关资源
    最近更新 更多