Я пытаюсь использовать сертификат из хранилища сертификатов Windows для службы SOAP, но он всегда запрашивает сертификат с отображаемым диалоговым окном.
Мой код:
...
var RIO := THTTPRIO.Create(nil);
RIO.HTTPWebNode.HTTP.OnNeedClientCertificate := DoOnClientCertificateNeeded;
RIO.HTTPWebNode.GetHTTPReqResp.PreemptiveAuthentication := true;
var svc := wsETurizemPorocanje.GetrnoSoap(false, '', RIO);
data := TXmlData.Create;
data.LoadFromXml(xml.XML);
var errors := svc.oddajPorocilo('UserName', 'Password', data , 1);
...
end;
procedure TeTurizem.DoOnClientCertificateNeeded(const Sender: TObject; const ARequest: TURLRequest; const ACertificateList: TCertificateList; var AnIndex: Integer);
begin
for var idx := 0 to ACertificateList.Count - 1 do begin
if ACertificateList[idx].SerialNum = AppSettings.Server.Hostel.ETurizemSettings.CertSerial then begin
if (ACertificateList[idx].Start<=Now) and (ACertificateList[idx].Expiry>Now) then begin
AnIndex := idx;
break;
end else
raise Exception.Create('(DoOnClientCertificateNeeded) Client Certificate Expired.');
end;
end;
end;
Я схожу с ума, потому что не могу найти много документации или примеров.
Что мне нужно для предоставления сертификата вызова SOAP из хранилища сертификатов? Разве определения события недостаточно?
Вам необходимо определить обработчик событий со следующей сигнатурой:
procedure MyDoNeedClientCertificate(const Sender: TObject;
const ARequest: TURLRequest; const ACertificateList: TCertificateList;
var AnIndex: Integer);
procedure TForm1.MyDoNeedClientCertificate(const Sender: TObject; const ARequest: TURLRequest; const ACertificateList: TCertificateList;
var AnIndex: Integer);
begin
for var I := 0 to ACertificateList.Count - 1 do
begin
if ACertificateList[I].CertName.Contains(edCertName.Text) then
begin
if ACertificateList[I].Expiry > now then
begin
AnIndex := I;
Exit;
end;
end;
end;
end;
Затем свяжите это с событием HTTPRIO.HTTPWebNode.OnBeforePost:
procedure TForm1.HTTPRIO1HTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp; Client: THTTPClient);
begin
HTTPReqResp.OnNeedClientCertificate := MyDoNeedClientCertificate;
end;
Таким образом вы привязываете обработчик событий после его перезаписи в процедуре SetupHttp.
Процедура запущена, но возникла новая проблема - сайт возвращает ошибку «Запрещено (403) — 'wwwt.ajpes.si/rno/rnoApi/eTurizem/….». Если я удалю событие, меня попросят предоставить сертификат, и метод сервера будет выполнен правильно.
И этот метод, и тот, в котором вы выбираете набор сертификатов AIndex. Перейдите к коду Delphi, чтобы увидеть, какой AIndex работает и почему он выдает другой, который не работает.
Спасибо за подсказку - ошибка действительно была. Я изменил «CertName» на «SerialNum», и это сработало! Большое спасибо всем!
Это связано с тем, что когда вы вызываете код httprio, он перезаписывает ваш обработчик событий. Проверьте процедуру THTTPReqResp.SetupHttp(Http: THttpClient); в модуле Soap.SOAPHTTPTrans. "FHTTP.OnNeedClientCertificate := DoNeedClientCertificate"; Я бы почти сказал, что это ошибка.