首页 > 解决方案 > DelphiXE8 和 WSDL,禁用通过 Smart Card Reader 的身份验证

问题描述

使用 Delphi XE8,我导入了一个 WSDL 并使用 HTTPRIO 组件进行身份验证:

property HTTPRIO:
  HTTPWebNode ->
    ClientCertificate ->  CertName = ServiceSSL.cer
    InvokeOptions [soIgnoreInvalidCerts,soPickFirstClientCertificate]
 Event HTTPRIO
    HTTPWebNode -> OnBeforePost = HTTPRIO1HTTPWebNode1BeforePost


procedure HTTPRIO1HTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp;
  Data: Pointer);
var
 auth: String;
 FUserName, FPassword : string;
begin
 FUserName:=UtenteTS;
 FPassword:=PassTS;
 auth := 'Authorization: Basic ' + TNetEncoding.Base64.Encode(FUserName + ':' + FPassword);
 HttpAddRequestHeaders(Data, PChar(auth), Length(auth), HTTP_ADDREQ_FLAG_ADD);
end;

效果很好。

问题是:当带有数字签名卡的智能卡读卡器插入 PC 时,在身份验证期间它与智能卡通信,打开 PIN 请求窗口。

在此处输入图像描述

我不想要这个,我想优先通过 HTTPRIO1HTTPWebNode1BeforePost 进行身份验证!

笔记:

运行调试,HTTPRIO1HTTPWebNode1BeforePost,它被处理,然后开始与智能卡的通信。如何禁用智能卡读卡器读取?

我需要将带有数字签名的卡连接到 PC,因为我的程序必须对文档进行数字签名。

我添加细节。

我注意到在调用 HTTPRIO1HTTPWebNode1BeforePost 之后

此代码执行两次

 { line 1151 of soap.SOAPHTTPtrans.pas  Posting Data Event }
      if Assigned(FOnPostingData) then
        FOnPostingData(DatStr.Size, BuffSize);

      RetVal := ERROR_SUCCESS;
{$IFDEF UNICODE}
      HttpSendRequest(Request, nil, 0,
                      DatStr.Bytes, DatStr.Size);
{$ELSE}
      HttpSendRequest(Request, nil, 0,
                      @DatStr.DataString[1],
                      Length(DatStr.DataString));
{$ENDIF}
      RetVal := HandleWinInetError(GetLastError, Request, True);

      case RetVal of
        ERROR_SUCCESS: break;
        ERROR_CANCELLED: System.SysUtils.Abort;
        ERROR_INTERNET_FORCE_RETRY: {Retry the operation};
      end;

第一个 RetVal pass 的值为 12032 = ERROR_INTERNET_FORCE_RETRY: {Retry the operation};

第二步 HttpSendRequest(Request, nil, 0, DatStr.Bytes, DatStr.Size); 启动智能卡读卡器并打开消息登录窗口,该窗口要求输入读卡器中数字签名的 PIN。RetVal = 0

我尝试使用 InternetSetOption(Data, INTERNET_FLAG_NO_AUTH, ????, ????) 但我不知道该怎么做。

我不想打开登录消息框,请求智能卡 PIN。我能怎么做?


更新我的请求

读完后:我试过这个:发布“用WinHTTP组件替换WinINet。两者都有非常接近的API,第二个不会创建任何UI交互,但会返回错误代码,就像任何其他API一样。WinINet的UI部分可能对于某些软件来说是个好主意,但听起来好像不符合您的需求。”

如何将 winHttp 与 HttpRio 一起使用?我试过了:

uses winHTTP;
...
procedure HTTPRIOHTTPWebNode1BeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);

auth := 'Authorization: Basic ' + TNetEncoding.Base64.Encode(FUserName + ':' + FPassword);

if not WinHttpAddRequestHeaders(Data, PChar(auth), Length(auth), WinHTTP_ADDREQ_FLAG_ADD) then ShowMessage('demat WinHttpAddRequestHeaders:  ' + SysErrorMessage(GetLastError()));

如果我使用 HttpAddRequestHeaders(在 winInet.dll 中)它可以工作:

HttpAddRequestHeaders(Data, PChar(auth), Length(auth), HTTP_ADDREQ_FLAG_ADD)

如果我使用 WinHttpAddRequestHeaders(在 winhttp.dll 中)它不起作用,并且我收到错误:无效句柄。:

句柄是数据类型点。

关于 HINTERNET 句柄的帖子中 “Microsoft Win32 Internet (WinInet) 函数也使用 HINTERNET 句柄。但是,WinInet 函数中使用的句柄不能与 WinHTTP 函数中使用的句柄互换。有关 WinInet 的更多信息,请参阅关于 WinINet。”

所以我不能将 WinHttpAddRequestHeaders 与 Httprio 一起使用。对不起。

" WinHttpAddRequestHeaders(Data, PChar(auth), Length(auth), WinHTTP_ADDREQ_FLAG_ADD) 我想尝试使用带有 HttpRio 而不是 winInet 的 winHttp。正如我所读到的,使用 winHttp,我不会收到 Windows 安全窗口(PIN 请求)。我不知道如何在 HttpRio 中使用 winHttp。”你能帮帮我吗?

标签: wsdlbasic-authenticationdelphi-xe8smartcard-reader

解决方案


推荐阅读