如何在Delphi 10.3.2的HttpRIO(SOAP)中使用双向SSL?
我之前在Delphi 10.3.x版本里折腾过HttpRIO的双向SSL配置,刚好碰到过证书存在PKI卡的场景,给你分享下实际可行的步骤和代码示例,应该能帮你解决问题~
在Delphi 10.3.2的HttpRIO中配置双向SSL
1. 先确认PKI卡的证书能被系统识别
- 先打开Windows证书管理器(通过
certmgr.msc命令即可打开),检查你的PKI卡证书是否在个人存储区里正常显示。如果能看到,说明系统已经正确识别了PKI卡,这一步没问题。 - 如果看不到,得先安装PKI卡对应的驱动程序,确保卡片能被系统正常读取。
2. 配置HttpRIO的SSL处理器
HttpRIO底层依赖Indy的TIdSSLIOHandlerSocketOpenSSL,我们需要给它绑定SSL处理器并配置客户端证书相关选项。下面是完整的代码示例:
uses Soap.Httprio, IdSSLOpenSSL, IdSSL, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP, SysUtils; procedure SetupMutualSSLForHttpRIO(AHttpRIO: THTTPRIO; const ACertSubject: string); var SSLHandler: TIdSSLIOHandlerSocketOpenSSL; TargetCert: TIdX509Certificate; begin // 创建SSL处理器实例 SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil); try // 配置SSL版本:根据服务端支持的版本调整,这里选TLS1.2和1.3兼容性较好 SSLHandler.SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_3]; // 设置为客户端模式,开启服务端证书验证 SSLHandler.SSLOptions.Mode := sslmClient; SSLHandler.SSLOptions.VerifyMode := [sslvrfPeer]; SSLHandler.SSLOptions.VerifyDepth := 2; // 从系统证书存储中查找PKI卡的证书 // 这里用证书主题查找,你也可以换成证书指纹(Thumbprint)来精确匹配 TargetCert := SSLHandler.SSLOptions.Certificates.FindCertificate('', ACertSubject); if not Assigned(TargetCert) then raise Exception.CreateFmt('未找到主题为【%s】的客户端证书,请检查PKI卡是否正确读取', [ACertSubject]); // 绑定客户端证书:PKI卡的私钥不需要手动加载,系统会自动调用卡驱动获取 SSLHandler.SSLOptions.Cert := TargetCert; // 将SSL处理器绑定到HttpRIO AHttpRIO.IOHandler := SSLHandler; // 确保请求URL是HTTPS协议 AHttpRIO.URL := StringReplace(AHttpRIO.URL, 'http://', 'https://', [rfIgnoreCase]); except SSLHandler.Free; raise; end; end; // 调用示例:假设你已经通过WSDL导入了SOAP客户端类TMySOAPService procedure TMainForm.CallSOAPServiceWithMutualSSL; var SOAPClient: TMySOAPService; begin SOAPClient := TMySOAPService.Create(nil); try // 替换成你PKI卡证书的主题名称(从证书管理器里复制) SetupMutualSSLForHttpRIO(SOAPClient.HTTPRIO, 'CN=你的姓名,O=你的公司名称'); // 调用你的SOAP方法 SOAPClient.YourSOAPMethod(); finally SOAPClient.Free; end; end;
3. 常见问题排查
- 证书找不到:如果用主题找不到证书,试试用证书的**指纹(Thumbprint)**查找,把
FindCertificate的第一个参数换成指纹字符串,第二个参数留空。指纹可以从证书管理器的证书详情里复制。 - OpenSSL版本问题:Delphi 10.3.2自带的OpenSSL版本偏旧,建议替换成OpenSSL 1.1.x系列的版本(注意对应程序的32/64位),把对应的
libcrypto-1_1.dll和libssl-1_1.dll放到程序目录下。 - PIN码输入问题:有些PKI卡需要输入PIN码,正常情况下系统会自动弹出PIN输入框;如果没弹,可以给SSLHandler绑定
OnGetPassword事件,手动弹出输入框获取PIN码。 - 服务端拒绝连接:确认服务端已经配置了信任客户端证书的CA,否则服务端会在SSL握手时拒绝客户端的请求。
4. 额外小技巧
可以用Wireshark抓包,查看SSL握手阶段的报文,确认客户端是否成功发送了证书给服务端,这能帮你快速定位是客户端配置问题还是服务端的问题。
内容的提问来源于stack exchange,提问作者Mystic Boris
相关产品推荐
相关产品推荐

