当前位置: 首页 > web >正文

Indy HTTP Server 使用 OpenSSL 3.0

前言

使用 Indy HTTP Server 做一个 Web Server 或者一个 WebService Server,如果使用 Delphi 默认的 TIdServerIOHandlerSSLOpenSSL,只能加载 OpenSSL 1.0 的 DLL 库。

现如今 OpenSSL 已经是 3.0 了。

还好网上有开源的 TTaurusTLSServerIOHandler 可以用来替换 TIdServerIOHandlerSSLOpenSSL 加载 OpenSSL 3.0 的 DLL 库。

以下描述,基于 Delphi 12 社区版。

如何使用

OpenSSL 1.x 的库

首先,如果使用 TIdServerIOHandlerSSLOpenSSL 加载 OpenSSL 1.0 的动态链接库,应该给程序准备:

1. libeay32.dll

2. ssleay32.dll

上述两个文件的下载地址,请参考:

Securing Indy Network Connections - RAD Studio

上面那篇官方文档里面提到的下载地址是:

Index of /SSL

OpenSSL 3.x 的库

如果使用 OpenSSL 3.0 的动态链接库,则应该是给程序以下两个文件:

1. libcrypto-3.dll

2. libssl-3.dll

上述两个 OpenSSL 3.x 的文件的下载地址,在:

https://github.com/JPeterMugaas/TaurusTLS/tree/main

这个地址的首页里面有提供。

关于 TaurusTLS 的使用

首先去 https://github.com/JPeterMugaas/TaurusTLS/tree/main 下载这个控件的源代码。

然后在 Delphi 里面安装它。

问题:

它的官方页面里面提到:

  1. Set the INDY_PATH environment variable for your user account to the location where Indy is located.
  2. Open TaurusForIndy290All.groupproj in the TaurusTLS\Packages\d12 folder.
  3. Compile TaurusTLS_RTForIndy290.
  4. Compile TaurusTLS_DTForIndy290 and install it in the IDE.

但实际上,按照上述说法,没法安装。

问题的详情

TaurusTLS_RTForIndy290 的源文件里面:

requiresrtl,IndyCore290,IndySystem290,IndyProtocols290;

实际上 Delphi 自带的 Indy 里面,没有 IndyCore290.dcp 等上述三个带 290 的文件。

把上述代码的 290 删除掉,仅仅留下 IndyCore 以及另外两个同样去掉 290 的引用,编译能够通过,但整个硬盘到处找,也找不到编译后的 bpl 文件。

问题的解决

仔细观察这个控件所在的文件夹:

Delphi\Controls\TaurusTLS-main\Packages\d12

发现里面实际上有两个包文件,名字是:

TaurusTLS_RT.dpk

TaurusTLS_DT.dpk

打开这两个包文件来编译,安装控件成功!

因此,不应该按照它的说明,编译 TaurusTLS_DTForIndy290.dpk 和 TaurusTLS_RTForIndy290.dpk 这两个项目。

使用注意

在 Delphi 中创建一个 Soap Server 项目,选择 Stand alone 模式,因此它就自带了 Indy HTTP Server 作为内置的 Web Server。创建项目时,那个 https 的检查框不要勾选。

程序有了以后,顺便创建一个 WebService 的接口。给接口搞一个函数。我这里是:

{ Invokable interface IIndySSLTaurus }unit IndySSLTaurusIntf;interfaceuses Soap.InvokeRegistry, System.Types, Soap.XSBuiltIns;type{ Invokable interfaces must derive from IInvokable }IIndySSLTaurus = interface(IInvokable)['{CA6E9719-4ABF-4E22-8E81-C74231025E99}']{ Methods of Invokable interface must not use the default }{ calling convention; stdcall is recommended }function Hello(const S: string): string; stdcall;end;implementationinitialization{ Invokable interfaces must be registered }InvRegistry.RegisterInterface(TypeInfo(IIndySSLTaurus));end.

上述接口的实现部分的代码:

{ Invokable implementation File for TIndySSLTaurus which implements IIndySSLTaurus }unit IndySSLTaurusImpl;interfaceuses Soap.InvokeRegistry, System.Types, Soap.XSBuiltIns, IndySSLTaurusIntf;type{ TIndySSLTaurus }TIndySSLTaurus = class(TInvokableClass, IIndySSLTaurus)publicfunction Hello(const S: string): string; stdcall;end;implementation{ TIndySSLTaurus }function TIndySSLTaurus.Hello(const S: string): string;
beginResult := 'Hello, ' + S;
end;initialization
{ Invokable classes must be registered }InvRegistry.RegisterInvokableClass(TIndySSLTaurus);
end.

这个项目,Delphi IDE 默认给出的是 8080 端口。运行它。

然后,做一个 WebService 客户端程序,拖一个 HTTPRIO1 这个控件到 Form 上面。

这个时候,还没有实现 https,因此,给这个 HTTPRIO1.URL 赋值:

http://localhost:8080/soap 就可以了。

给客户端写测试代码:

procedure TForm2.Button1Click(Sender: TObject);
varIntf: IIndySSLTaurus;
beginIntf := HTTPRIO1 as IIndySSLTaurus;tryMemo1.Lines.Add(Intf.Hello(Edit1.Text));finallyIntf := nil;end;
end;

运行客户端,点击按钮,能够在 Memo1 里面看到从服务器端正确返回的值。测试通过。

为服务器端增加 OpenSSL 3.x 的支持

从控件面板,拖一个 TaurusTLSServerIOHandler1 到主界面上。然后为服务器端增加以下代码:

procedure TForm1.FormCreate(Sender: TObject);
beginFServer := TIdHTTPWebBrokerBridge.Create(Self);//必须用代码指定。设计期在属性面板里面指定的证书文件,没有效果。TaurusTLSServerIOHandler1.DefaultCert.PublicKey := 'mysite.net.cert.pem';TaurusTLSServerIOHandler1.DefaultCert.PrivateKey := 'mysite.net.key.pem';FServer.OnQuerySSLPort := OnQuerySSLPort;//写绝对路径也没问题
//  TaurusTLSServerIOHandler1.DefaultCert.PublicKey := 'D:\TestD12\IndySSL_Taurus\证书备份\mysite.net.cert.pem';
//  TaurusTLSServerIOHandler1.DefaultCert.PrivateKey := 'D:\TestD12\IndySSL_Taurus\证书备份\mysite.net.key.pem';FServer.IOHandler := TaurusTLSServerIOHandler1; TaurusTLS.LoadOpenSSLLibrary;
end;procedure TForm1.OnQuerySSLPort(APort: TIdPort; var AUseSSL: Boolean);
beginAPort := 8080;   //如果不加上这个,就只能走默认的 443AUseSSL := True;
end;

剩下的代码就是 Delphi IDE 在创建这个 Soap Server 的时候自动创建的代码了,如下:

procedure TForm1.StartServer;
beginif not FServer.Active thenbeginFServer.Bindings.Clear;FServer.DefaultPort := StrToInt(EditPort.Text); //这里默认是 8080FServer.OnQuerySSLPort := OnQuerySSLPort;FServer.Active := True;end;
end;

另外,还有个事件方法,是关于证书的密码的:

procedure TForm1.TaurusTLSServerIOHandler1GetPassword(ASender: TObject;var VPassword: string; const AIsWrite: Boolean; var VOk: Boolean);
beginVPassword := '';
end;

我的证书是自签发证书,没有密码。因此这个事件方法没有也能运行。

到这里,这个支持OpenSSL  3.x 的 https 的 Soap Server 就可以使用了。编译运行它。

把前面的客户端的 URL 改为:https://localhost:8080/soap 然后运行客户端,测试通过。

需要注意的问题

我在前面的代码里面,为这个控件,赋值了证书文件名:

TaurusTLSServerIOHandler1.DefaultCert.PublicKey := 'mysite.net.cert.pem';TaurusTLSServerIOHandler1.DefaultCert.PrivateKey := 'mysite.net.key.pem';

实际上,它在设计期的属性面板里面,有这两个属性。

但是,如果我们在设计期的属性面板里面填写上面的两个文件名,不管是填文件名,还是填写带绝对路径的文件名,只要没有用代码为它赋值,都不能正常工作。

对比起来,如果采用 Indy 自己的 IdServerIOHandlerSSLOpenSSL1(只支持 OpenSSL 1.x)的话,设计期填写的上述属性,也是能够正常工作的。

还有一个小问题

因为我使用的是自己签发的证书,所以在测试中,在 Debug 状态下,用浏览器访问本程序,Delphi IDE 会弹出不少异常提示,然后浏览器还是能够显示这个 Soap Server 的首页。但此时如果点击首页上的其它链接,比如查看接口,就会出错到页面完全无法显示。

但是,如果此时是使用 Delphi 自己的 Web Service 客户端去访问这个服务器,调用接口函数,没有任何问题,也没有异常错误提示。

结束

使用 Taurus 这个控件,确实能够让 Indy 调用 OpenSSL 3.x 的 DLL 库。

http://www.xdnf.cn/news/18783.html

相关文章:

  • 知识蒸馏 Knowledge Distillation 1. 监督式微调(SFT):极大似然是前向 KL 的特例
  • Grafana k6 性能测试
  • 深度模块化剖析:构建一个健壮的、支持动态Cookie和代理的Python网络爬虫
  • 保姆级Maven安装与配置教程(Windows版)
  • 基于 MATLAB 的信号处理实战:滤波、傅里叶变换与频谱分析
  • 从文本树到结构化路径:解析有限元项目架构的自动化之道
  • 服务器硬件电路设计之 SPI 问答(四):3 线 SPI、Dual SPI 与 Qual SPI 的奥秘
  • Leetcode 3660. Jump Game IX
  • k8sday16调度器
  • MSF基础知识
  • Java 内存模型(JMM)与并发可见性:深入理解多线程编程的基石
  • Java:HashMap的使用
  • K8s 实战:六大核心控制器
  • 什么是 Nonce?
  • 电力电子simulink练习10:反激Flyback电路搭建
  • Linux 的 TCP 网络编程常用API
  • 图像均衡化详解:从直方图均衡到 CLAHE,让图片告别 “灰蒙蒙“
  • 高数 不定积分(4-3):分部积分法
  • 使用虚幻引擎5(UE5)开发类似《原神》的开放世界游戏:从技术架构到实践指南
  • 内网后渗透攻击--域控制器安全(1)
  • 单表查询-分析函数的应用
  • 重置MySQL数据库的密码指南(Windows/Linux全适配)
  • 在 Ruby 客户端里用 ES|QL
  • WSL-linux部署IndexTTS 记录(含本地 CUDA/cuDNN 编译依赖说明)
  • 鸿蒙 ArkTS 开发:Number、Boolean、String 三种核心基本数据类型详解(附实战案例)
  • 夜间跌倒检测响应速度↑150%!陌讯多模态骨架追踪算法在智慧养老院的落地实践
  • 手写MyBatis第32弹-设计模式实战:Builder模式在MyBatis框架中的精妙应用
  • Anaconda搭建keras开发环境小记
  • EP01:【DA】数据分析的概述
  • 【LeetCode】分享|如何科学的刷题?