我该如何进行HTTPS SOAP服务的身份验证?

6
我正在尝试创建一个小工具,可以监控我从ISP使用了多少带宽以及还剩下多少。他们有一个SOAP服务,我必须通过我的用户名和密码进行身份验证并验证客户端,然后我将得到2个GUID,必须将其传递到从数组返回使用统计信息的函数中。然后这些数据将被缓存1小时,之后我必须再次进行身份验证。
我已经在Delphi 2010内使用WSDL导入程序生成了一个单元。(不确定是否应该发布,因为它相当大)
我正在尝试使用以下代码对第一部分进行身份验证:
procedure TForm1.btnAuthClick(Sender: TObject);
var
  fGUID: string;
begin
  HTTPRIO1.URL := 'https://webservices.zen.co.uk/broadband/v3.11/serviceengine.asmx?WSDL';
  try
    fGUID := (HTTPRIO1 as ServiceEngineSoap).Authenticate(edtUserName.Text,edtPassword.Text);
    Label1.Caption := fGUID;
  except
    on E: Exception do
    Memo1.Lines.Text := E.Message;
  end;
end;

上述代码总是返回以下错误:

消息中需要但未出现最终接收者的标头http://schemas.xmlsoap.org/ws/2004/08/addressing:Action

我尝试使用WSDLLocation替换服务和端口。
procedure TForm1.btnAuthClick(Sender: TObject);
var
  fGUID: string;
begin
  HTTPRIO1.WSDLLocation := 'https://webservices.zen.co.uk/broadband/v3.11/serviceengine.asmx?WSDL';
  HTTPRIO1.Service := 'ServiceEngine';
  HTTPRIO1.Port := 'ServiceEngineSoap';
  try
    fGUID := (HTTPRIO1 as ServiceEngineSoap).Authenticate(edtUserName.Text,edtPassword.Text);
    Label1.Caption := fGUID;
  except
    on E: Exception do
    Memo1.Lines.Text := E.Message;
  end;
end; 

这将始终生成以下错误:

无法从WSDL“https://webservices.zen.co.uk/broadband/v3.11/serviceengine.asmx?WSDL”检索Service/Port'ServiceEngine'/'ServiceEngineSoap'的URL端点


我在这里做错了什么?如果我实际上应该发送标头,那么我如何才能通过身份验证来向服务进行认证?


请发布由WSDL导入器生成的单元,我认为这将有所帮助。 - Sam
我刚刚尝试编辑我的问题以包含单元,但它太长了:正文限制为30000个字符;您输入了53992个字符。 - Shambhala
1个回答

4
根据文档,如果服务器需要验证,使用THTTPReqResp对象的属性提供必要的信息。在THTTPReqResp对象中设置用户/密码(HTTPRIO1.HTTPWebNode.UserName := 'xxx'; HTTPRIO1.HTTPWebNode.Password := 'yyy')。此外,请注意使用HTTPS的文档:THTTPReqResp使用WinInet建立与服务器的连接。客户端系统必须安装wininet.dll。如果安装了IE3或更高版本,则可以在Windows系统目录中找到wininet.dll。WinInet具有提供安全连接(https)支持的优点。要使用WinInet,请在未定义USE_INDY符号的情况下编译项目。但是,根据下面的帖子,看起来这个用户/密码可能只用于代理情况。如果他们仍然没有解决这个问题,请按照Jean-Marie Babet的链接跟随原始解决方法(2007年)。

https://forums.codegear.com/thread.jspa?threadID=58755&tstart=0

这是解决方法:
处理HTTPRIO.HTTPWebNode组件的OnBeforePost事件,并使用InternetSetOption。以下是一个示例,该示例与MapPoint通信(MapPoint.NET使用“摘要”身份验证-一种“基本”身份验证的变体):
procedure TTestMapPointRender.HTTPRIO1HTTPWebNode1BeforePost(
  const HTTPReqResp: THTTPReqResp; Data: Pointer);
var
  UserName: string;
  PassWord: string;
begin
  UserName := GetWSToken('MapPoint', 'UserName');
  Password := GetWSToken('MapPoint', 'Password');
  if not InternetSetOption(Data,
               INTERNET_OPTION_USERNAME,
               PChar(UserName),
               Length(UserName)) then
     raiseException(SysErrorMessage(GetLastError));

  if not InternetSetOption(Data,
               INTERNET_OPTION_PASSWORD,
               PChar(Password),
               Length (Password)) then
     raiseException(SysErrorMessage(GetLastError));
end;

谢谢您的回复。GetWSToken是什么?我已经添加了wininet,但是找不到太多信息。它是未声明的标识符。 - Shambhala
GetWSToken看起来像是实现中的一个实用方法...你只需将其替换为您需要查找所需用户/密码的任何方法即可。 - Darian Miller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接