Delphi soap https authentication failure pops up a

2020-07-10 04:48发布

We have a delphi XE application that uses SOAP (THTTPRIO etc) communications which (in delphi) works over WinInet.dll, by default. We fixed the authentication code so that it works, using https authentication, and when the user name and password for https are correct, everything is fine.

The problem is that when authentication details are incorrect, you get a message box from Windows, that is probably being popped up by WinInet.dll itself. I want to make that dialog box go away. I can't figure out how to change my Delphi SOAP so the password won't come up.

The situation is different than this question in the following ways:

  1. I am doing all the things that he is doing, including calling InternetSetOption(...) to set the user name and password.

  2. I am not using a server with a self-signed certificate, so the soIgnoreInvalidCerts flag is not applicable to my case.

  3. Somehow, I think I need to get some API calls into WinInet to tell it not to pop up the InternetErrorDlg that it has (some versions of windows say Windows Security Options) that pops up to ask the user.

  4. In my case the user name and password we have in our configuration file is being used, it is wrong (out of date) and so we want the WinInet code to simply return an error instead of popping up the dialog box.

Perhaps the other question the guy really did figure out how to do this, but the detail on that question is insufficient to see how he did it. The accepted answer does not work for me.

Some dead ends I've followed:

WinInet MSDN docs for PLUGIN_AUTH_FLAGS_CAN_HANDLE_UI - that doesn't appear to be applicable to a WinInet user, rather to a plugin.

WinInet MSDN docs discuss InternetSetOption, and some newsgroups have lead me to the following on-before-post event handler code:

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;

This code makes the password work, but when the user's entered password is wrong, how do I get the SOAP call to fail, or raise an exception, instead of popping up a message box?

2条回答
ら.Afraid
2楼-- · 2020-07-10 05:34

Try modifying SOAPHTTPTrans to handle the error silently. In THTTPReqResp.HandleWinInetError, there is ultimately a call to the error dialog:

  Result := CallInternetErrorDlg

You can probably detect your particular error, you should be able to return a 0 from HandleWinInetError, or at least NOT make a call to CallInternetErrorDlg. See if that helps.

查看更多
Explosion°爆炸
3楼-- · 2020-07-10 05:46

Replace WinINet by WinHTTP component. Both have very close APIs, and the 2nd does not create any UI interaction, but will return error codes, just like any other API. The UI part of WinINet may be a good idea for some software, but it sounds like if does not fit your needs.

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

Of course, HTTPS and authentication will be handled in a similar manner. But you'll have to prompt for the user name and password, and update the HTTP headers as requested. See this link.

From our tests, WinHTTP is much faster than WinINet (certainly because it does not implement any UI part, and is not linked to Internet Explorer libraries).

You can take a look at our Open Source classes to guess how small is the difference in the API between WinINet and WinHTTP (most code is shared in the linked unit).

查看更多
登录 后发表回答