TIdHTTP配置SSL证书固定后经代理出现HTTPS转HTTP异常
首先可以明确:这不是Indy组件的Bug,而是你的证书固定实现存在疏漏,加上Fiddler配置与Indy的交互逻辑导致了这个异常现象。下面具体拆解问题原因和修复方案:
核心问题点
1. 硬编码的证书指纹已失效
Google的SSL证书会定期更新,你代码里硬编码的SHA256指纹98:1D:34:C4:F8:4A:F2:B7:C7:AB:77:AD:51:1C:51:4C:AD:76:ED:0D:0E:FA:C9:63:68:AF:28:69:94:60:BF:7A大概率已经过期,这直接导致第一次请求时证书指纹验证失败,抛出异常。
2. 未正确处理请求后的连接状态
第一次验证失败抛出异常后,Indy的TIdHTTP连接处于异常状态,第二次请求时没有重新初始化SSL握手流程,反而意外降级为HTTP请求(绕过了SSL层),这就是为什么Fiddler显示未加密流量且请求成功的原因。
3. Fiddler配置冗余
你取消了“Decrypt HTTPS traffic”却又安装了Fiddler证书,这是多余操作,反而可能干扰Indy的SSL握手逻辑。
修复方案
1. 更新目标网站的证书指纹
打开浏览器访问https://www.google.com,查看当前证书的SHA256指纹(不同浏览器操作略有差异,比如Chrome可通过「开发者工具→安全→查看证书→详细信息→指纹」获取),替换代码中硬编码的LCGoogleCert值。
2. 修正证书固定的验证逻辑
在OnVerifyPeer事件中增加证书非空判断,避免空指针风险,同时明确验证逻辑:
function TForm2.SSLIOHandlerVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean; const LCGoogleCert = '替换为最新的SHA256指纹'; begin Result := False; // 先确保证书对象有效 if Certificate <> nil then begin // 仅验证指纹,忽略系统默认的证书链验证(证书固定的核心逻辑) Result := Certificate.Fingerprints.SHA256AsString.Equals(LCGoogleCert); end; end;
3. 每次请求前重置连接状态
在按钮点击事件中,每次请求前主动断开现有连接,确保重新建立干净的SSL握手:
procedure TForm2.Button1Click(Sender: TObject); const LCGoogleURL = 'https://www.google.com/'; var s: UnicodeString; begin // 断开旧连接,强制重新初始化SSL if HTTPSender.Connected then HTTPSender.Disconnect; s := HTTPSender.Get(LCGoogleURL); end;
4. 调整Fiddler配置(可选)
如果只是测试证书固定功能,只需保留「Capture HTTPS Connects」勾选,取消「Decrypt HTTPS traffic」,无需安装Fiddler证书,这样Fiddler只会转发HTTPS流量,不会干扰Indy与目标服务器的SSL握手。
内容的提问来源于stack exchange,提问作者Maxim

