3
votes

I'm connecting to a web service using basic authentication using the following code:

var
  RIO: THTTPRIO;
begin
  RIO := THTTPRIO.Create(nil);

  EndPoint := GetWebServicePort(True, '', RIO);

  RIO.HTTPWebNode.UserName := 'xxxx';
  RIO.HTTPWebNode.Password := 'yyyy';
...
end;

If the username and password are correct, everything works fine. However, if they are not correct, a Windows dialog pops up requesting the correct credentials. Instead of the dialog I need to catch the error.

enter image description here

How do I stop the dialog popping up? I've searched and found a couple of results (Link 1, Link 2), but neither seems offer a real solution.

1
This is an old unsolved bug in THttpRio component. Use instead Indy - RBA
This is because the web service implementation in Delphi uses the "wrong" Windows API - using WinInet instead of WinHTTP. As MSDN explicitly says (msdn.microsoft.com/en-us/library/windows/desktop/…), "WinINet displays a user interface for some operations such as collecting user credentials. WinHTTP, however, handles these operations programmatically." It's also very dangerous because if you use it in a service, the service may "hang" waiting on user input that could never be entered because the dialog is not shown in any user accessible desktop. - LDS
Not sure if this is useful as I haven't tried myself and I am not sure it would halt the Windows dialog, but maybe the event handler HTTPRIO.HTTPWebNode.OnWinInetError can come in hand? You would need to check for the HTTP_STATUS_PROXY_AUTH_REQ error. - Guillem Vicens
Note that it looks like you can use WinHTTP with Delphi SOAP: see stackoverflow.com/questions/26911550/… - mjn
@mjn - Even after defining USE_INDY, the dialog still appears. - norgepaul

1 Answers

1
votes

To catch the error, you can use a HTTP client library, for example Indy TIdHTTP, to run a HTTP GET (or HEAD) request on the web service address first, and catch the exception which is thrown when user / password are wrong.

uses
  ... IdHTTP ...;

...
var
  HTTP: TIdHTTP;

ValidCredentials := False;
...    
HTTP.Request.Username := username;
HTTP.Request.Password := password;
HTTP.Request.BasicAuthentication := True;
try
  HTTP.Head(url);
  ValidCredentials := HTTP.ResponseCode = 200;
except
  on ... (some Indy exception) do
  begin
    // signal that username / password are incorrect
    ...
  end;
end;

if ValidCredentials then
begin
  // invoke Web Service ...