为什么两个在不同连接上调用HttpSendRequest(新的InternetOpen和新的InternetConnect)会带来不同的结果?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么两个在不同连接上调用HttpSendRequest(新的InternetOpen和新的InternetConnect)会带来不同的结果?相关的知识,希望对你有一定的参考价值。

我正在使用wininet连接到需要客户端证书的URL。为了测试我的“自动纠错”,我在没有客户端证书的情况下进行此连接,并且行为是调用我的SelectCertificate函数。

故意我没有将所有参数传递给这个函数,当然,引发异常并且我的请求被中止。有清洁块可以进行所有必要的清理[InternetCloseHandle(HttpOpenRequestHandle),InternetCloseHandle(InternetConnectHandle)和InternetCloseHandle(InternetOpenHandle)]。

第一个请求返回正确的异常,由于缺少客户端证书,但第二个(新的?)请求引发另一个异常“安全通道支持错误”(错误12157)

为了澄清,请参阅以下流程:

第一个请求

1.0 InternetOpen(...)

2.0 InternetConnect(...)

3.0 HttpOpenRequest(...)

4.0 HttpSendRequest(..)

  4.1 Error (ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED)

  4.2 SelectCertificate

    4.2.1 Raise exception because I intentionally do not passed all parameters

5.0 InternetCloseHandle(HttpOpenRequestHandle)

6.0 InternetCloseHandle(InternetConnectHandle)

7.0 InternetCloseHandle(InternetOpenHandle);

第二个(新的?)请求

1.0 InternetOpen(...)

2.0 InternetConnect(...)

3.0 HttpOpenRequest(...)

4.0 HttpSendRequest(..)

  4.1 Error (ERROR_INTERNET_SECURITY_CHANNEL_ERROR)

  4.2 I do not know how to handle this error, so...

  4.3 Raise the original exception "Secure Channel Support Error"

5.0 InternetCloseHandle(HttpOpenRequestHandle)

6.0 InternetCloseHandle(InternetConnectHandle)

7.0 InternetCloseHandle(InternetOpenHandle)

从现在开始的所有其他请求就像第二个请求一样。

我的问题是:

当我关闭所有句柄并进行“全新连接”时,调用之间的结果应该不一样?

如果没有,为什么?

有一种方法可以进行全新连接吗?怎么样?

实际上,我只是通过关闭整个应用程序来获得一个全新的连接:(并重新开始

答案

问题是由某种SSL缓存引起的,可以通过在请求之前执行以下代码块来擦除:

type
    TSslEmptyCache = function (pszTargetName: LPSTR; dwFlags: DWORD): BOOL; WINAPI;
    TIncrementUrlCacheHeaderData = function (nIdx: DWORD; lpdwData: LPDWORD): BOOL; WINAPI;

var
    SchannelDLLHandle, WinInetHandle: HMODULE;
    SslEmptyCache: TSslEmptyCache;
    IncrementUrlCacheHeaderData: TIncrementUrlCacheHeaderData;

SchannelDLLHandle := LoadLibrary('schannel.dll');
WinInetHandle := LoadLibrary('wininet.dll');

if (SchannelDLLHandle > 0) and (WinInetHandle > 0) then
    try
    SslEmptyCache := GetProcAddress(SchannelDLLHandle,'SslEmptyCacheW');
    IncrementUrlCacheHeaderData := GetProcAddress(WinInetHandle,'IncrementUrlCacheHeaderData');
    if Assigned(SslEmptyCache) and Assigned(IncrementUrlCacheHeaderData) then
    begin
      SslEmptyCache(nil,0);
      IncrementUrlCacheHeaderData(14,@buffer);
    end;
    finally
        FreeLibrary(SchannelDLLHandle);
    FreeLibrary(WinInetHandle);
    end;

有关更多信息,请阅读this article

以上是关于为什么两个在不同连接上调用HttpSendRequest(新的InternetOpen和新的InternetConnect)会带来不同的结果?的主要内容,如果未能解决你的问题,请参考以下文章

gRPC原理详解

无法在 Symfony2 websocket 连接上调用函数

是否可以在不同的连接上执行 CallableStament?

如何在特定连接上使用不同的证书?

Tomcat 连接池问题 - 无法在关闭的连接上调用方法

Android WebView 无法在 WebRTC 对等连接上显示两个视频标签