Вопрос, поднятый пользователем, связан с использованием API WinInet для подключения к URL, который требует наличия клиентского сертификата. При первом запросе, в случае отсутствия необходимого сертификата, система корректно генерирует исключение ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED. Однако, при последующих запросах, несмотря на закрытие всех дескрипторов и попытку создания нового соединения, возникает другое исключение ERROR_INTERNET_SECURITY_CHANNEL_ERROR, которое приводит к ошибке "Secure Channel Support Error" (код ошибки 12157).
Описание проблемы
Пользователь сталкивается с проблемой, при которой повторные запросы через WinInet к URL, требующему клиентский сертификат, приводят к различным результатам. После первого запроса, при отсутствии сертификата, вызывается функция SelectCertificate, в которой намеренно не передаются все необходимые параметры, что приводит к исключению и отмене запроса. После закрытия дескрипторов соединения, при повторном запросе возникает другое исключение, связанное с безопасным каналом передачи данных.
Анализ проблемы
Пользователь закрывает все дескрипторы соединения и предполагает, что каждый последующий запрос будет осуществляться как новое соединение. Однако, результаты запросов различаются, что указывает на возможное сохранение состояния соединения даже после его закрытия.
Подтвержденный ответ
Проблема была вызвана кэшем 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;
begin
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;
end;
Помимо предложенного решения, можно также рассмотреть следующие шаги для устранения проблемы:
Проверка настроек кэша URL. Возможно, потребуется его очистка или изменение параметров.
Перезагрузка сетевых компонентов Windows, которые могут сохранять состояние соединения.
Использование других библиотек для работы с HTTP-запросами, если проблема не устраняется.
Заключение
При работе с клиентскими сертификатами и многократных запросах через WinInet важно учитывать возможное сохранение состояния соединения, которое может привести к неожиданным результатам. Очистка кэша SSL является эффективным решением для устранения данной проблемы.
Пользователь столкнулся с проблемой повторных запросов через WinInet, связанных с клиентскими сертификатами и безопасным каналом передачи данных, где после первого запроса возникает исключение об отсутствии сертификата, а при последующих запросах — ошибк
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS