Delphi TIdHTTP通过代理以HTTP的形式发送HTTPS请求
我在使用Delphi TIdHTTP通过代理以HTTP的形式发送HTTPS请求,delphi,fiddler,indy,delphi-xe8,idhttp,Delphi,Fiddler,Indy,Delphi Xe8,Idhttp,我在使用TIdHTTP实现SSL证书固定时遇到问题 因此,以下是步骤: 在表单上删除TIdHTTP、TIdSSLIOHandlerSocketOpenSSL和TIdCompressorZLib 将TIdSSLIOHandlerSocketOpenSSL和TIdCompressorZLib分配给TIdHTTP的IOHandler和Compressor属性 安装程序TIdSSLIOHandlerSocketOpenSSL: Port = 0 DefaultPort = 0 SSLOptions.Me
TIdHTTP
实现SSL证书固定时遇到问题
因此,以下是步骤:
Port = 0
DefaultPort = 0
SSLOptions.Method = sslvTLSv1_2
SSLOptions.SSLVersions = [sslvTLSv1_2]
SSLOptions.Mode = sslmClient
SSLOptions.VerifyMode = [sslvrfPeer]
SSLOptions.VerifyDepth = 0
OnVerifyPeer = SSLIOHandlerVerifyPeer
function TForm2.SSLIOHandlerVerifyPeer(Certificate: TIdX509; AOk: Boolean; ADepth, AError: Integer): Boolean;
const
LCGoogleCert = '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';
begin
Result := Certificate.Fingerprints.SHA256AsString.Equals(LCGoogleCert);
end;
procedure TForm2.Button1Click(Sender: TObject);
const
LCGoogleURL = 'https://www.google.com/';
var
s: UnicodeString;
begin
s := HTTPSender.Get(LCGoogleURL);
end;
在第一次调用
TIdHTTP.Get()
时,OnVerifyPeer
事件会看到Fiddler的SSL/TLS证书,而不是Google的证书,因此它会拒绝证书,并且底层套接字连接最终被关闭
但是,IOHandler的InputBuffer
(大约162字节的加密数据)中仍有未读数据。根据设计,TIdIOHandlerStack.Connected()
方法返回True,只要存在可满足读取操作的未读数据,即使没有物理套接字连接
因此,在第二次调用TIdHTTP.Get()
时,结果如下:
知道它正在通过代理通过HTTPS进行通信,并且它正在通过与先前调用TIdHTTP
相同的代理向同一个Google服务器发出新的HTTP请求。因此TIdHTTP.Get()
检查TIdHTTP
以查看它是否仍然连接到代理,并查看Connected()
最初为真,因此它决定跳过一个新的Connected()
请求,并像通过现有代理连接发送一个新的HTTP请求一样继续CONNECT
- 但是,由于基础套接字已断开连接,
必须与Fiddler建立新的套接字连接。在准备新的HTTP请求时,TIdHTTP
被清除InputBuffer
再次被选中,现在为False,因此Connected()
与Fiddler建立新的套接字连接。新的套接字连接最初是未加密的(IOHandler的TIdHTTP
设置为True),因此后续的PassThrough
不会被加密(但这段代码不知道CONNECT
已经决定跳过TIdHTTP
)CONNECT
继续将TIdHTTP
请求发送给未加密的FiddlerGET
- Fiddler将其TLS隧道缓存一段时间,因此它将现有隧道重新使用到Google,从而通过TLS连接将未加密的
原样转发到Google,然后将未加密的响应转发回GET
TIdHTTP
- 当发生需要关闭基础套接字的故障时,
不会清除TIdHTTP
。一个简单的解决方法是在执行任何其他操作之前,让InputBuffer
方法清除任何现有数据的TIdCustomHTTP.ConnectToHost()
。这样,在决定如何处理InputBuffer
之前,它会看到连接确实消失了。现在,我已将此修复程序签入Indy的SVN存储库,并在您的场景中进行了测试CONNECT
在它知道它正在对底层套接字做什么之前,过早地决定发送或跳过TIdHTTP
。这需要重新编写CONNECT
的内部逻辑,因此将推迟到Indy的更高版本TIdHTTP
- Fiddler正在通过先前加密的隧道来回转发未加密的数据。在
中对此无能为力TIdHTTP