Delphi soap https身份验证失败会弹出一个对话框

时间:2011-11-18 16:52:06

标签: delphi soap wininet

我们有一个使用SOAP(THTTPRIO等)通信的delphi XE应用程序,默认情况下(在delphi中)通过WinInet.dll工作。我们使用https身份验证修复了身份验证代码以使其正常工作,并且当https的用户名和密码正确时,一切正常。

问题是,当身份验证详细信息不正确时,您会从Windows获得一个消息框,这可能是由WinInet.dll本身弹出的。我想让那个对话框消失。我无法弄清楚如何更改我的Delphi SOAP,因此密码不会出现。

情况如下different than this question

  1. 我正在做他正在做的所有事情,包括调用InternetSetOption(...)来设置用户名和密码。

  2. 我没有使用带有自签名证书的服务器,所以soIgnoreInvalidCerts标志不适用于我的情况。

  3. 不知何故,我想我需要在WinInet中调用一些API来告诉它不要弹出它所拥有的InternetErrorDlg(某些版本的Windows称Windows安全选项)弹出来询问用户。

  4. 在我的情况下,我们在配置文件中使用的用户名和密码正在使用,这是错误的(过时的),因此我们希望WinInet代码只返回错误而不是弹出对话框框。

  5. 也许这个家伙确实知道如何做到这一点的另一个问题,但这个问题的细节不足以看出他是如何做到的。接受的答案对我不起作用。

    我遵循的一些死胡同:

    PLUGIN_AUTH_FLAGS_CAN_HANDLE_UI的WinInet MSDN文档 - 似乎不适用于WinInet用户,而是适用于插件。

    WinInet MSDN文档讨论了InternetSetOption,一些新闻组引导我进入以下on-before-post事件处理程序代码:

    procedure TMyDevice.HTTPWebNodeOnBeforePost(
      const HTTPReqResp: SOAPHTTPTrans.THTTPReqResp; Data: Pointer);
    var
     SecurityFlagsLen:DWORD;
     SecurityFlags:DWORD;
    begin
      { authentication, NTLM+HTTPS, WinInet authentication set via WinInet SET INTERNET OPTION API.
        This approach recommended on newsgroups for https basic authentication.  }
    
        if fUserName<>'' then
       if not InternetSetOption(Data,
                   INTERNET_OPTION_USERNAME,
                   PChar(fUserName),
                   Length(fUserName)) then
         raise EWebServiceAuthException.Create(SysErrorMessage(Windows.GetLastError));
    
       if fPassword<>'' then
      if not InternetSetOption(Data,
                   INTERNET_OPTION_PASSWORD,
                   PChar(fPassword),
                   Length (fPassword)) then
         raise EWebServiceAuthException.Create(SysErrorMessage(Windows.GetLastError));
    
          { possible type of hackage: WinInet Security option flags to stop password box? }
         SecurityFlagsLen := SizeOf(SecurityFlags);
          InternetQueryOption({Request}data, INTERNET_OPTION_SECURITY_FLAGS,
          Pointer(@SecurityFlags), SecurityFlagsLen);
          SecurityFlags := SecurityFlags or SECURITY_FLAG_something;
          InternetSetOption({Request}data, INTERNET_OPTION_SECURITY_FLAGS,
          Pointer(@SecurityFlags), SecurityFlagsLen);
    end;
    

    此代码使密码有效,但是当用户输入的密码错误时,如何让SOAP调用失败或引发异常,而不是弹出消息框?

2 个答案:

答案 0 :(得分:2)

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

请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/aa384068(v=vs.85).aspx

当然,HTTPS和身份验证将以类似的方式处理。但是您必须提示输入用户名和密码,并根据请求更新HTTP标头。请参阅this link

从我们的测试中,WinHTTP比WinINet快得多(当然因为它没有实现任何UI部分,并且没有链接到Internet Explorer库)。

您可以查看our Open Source classes来猜测WinINet和WinHTTP之间的API差异有多大(大多数代码在链接的单元中共享)。

答案 1 :(得分:0)

尝试修改SOAPHTTPTrans以静默处理错误。 在THTTPReqResp.HandleWinInetError中,最终会调用错误对话框:

  Result := CallInternetErrorDlg

您可能检测到您的特定错误,您应该能够从HandleWinInetError返回0,或者至少不调用CallInternetErrorDlg。看看是否有帮助。