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

时间:2018-02-06 20:11:46

标签: c++ windows delphi request wininet

我正在使用wininet连接到需要客户端证书的网址。为了测试我的“自动纠错”,我在没有客户端证书的情况下进行此连接,并且行为是调用我的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)

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

我的问题是:

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

如果没有,为什么?

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

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

1 个答案:

答案 0 :(得分:1)

问题是由某种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