【问题标题】:Delphi SOAP without WSDL: why is my function result nil没有 WSDL 的 Delphi SOAP:为什么我的函数结果为零
【发布时间】:2016-03-22 17:24:55
【问题描述】:

我尝试实现一个soap客户端,它应该调用这样的服务:

请求-XML:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope 
    xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

    <soapenv:Header>
        <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
            <wsse:BinarySecurityToken EncodingType="wsse:Base64Binary" ValueType="bipro:VDGTicket">ABCDEFG</wsse:BinarySecurityToken>
        </wsse:Security>
    </soapenv:Header>
    <soapenv:Body>
        <RequestSecurityToken xmlns="http://schemas.xmlsoap.org/ws/2005/02/trust">
            <TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</TokenType>
            <RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</RequestType>
        </RequestSecurityToken>
    </soapenv:Body>
</soapenv:Envelope>

回应:

<?xml version="1.0" encoding="UTF-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <soapenv:Body>
        <wst:RequestSecurityTokenResponse xmlns:wst="http://schemas.xmlsoap.org/ws/2005/02/trust">
            <wst:TokenType>http://schemas.xmlsoap.org/ws/2005/02/sc/sct</wst:TokenType>
            <wst:Lifetime>
                <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-22T13:11:53.053Z</wsu:Created>
                <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2016-03-22T17:11:53.053Z</wsu:Expires>
            </wst:Lifetime>
            <wst:RequestedSecurityToken>
                <wsc:SecurityContextToken xmlns:wsc="http://schemas.xmlsoap.org/ws/2005/02/sc">
                    <wsc:Identifier>bipro:1438029780641932842</wsc:Identifier>
                </wsc:SecurityContextToken>
            </wst:RequestedSecurityToken>
            <allgemein:BiPROVersion xmlns:allgemein="http://www.bipro.net/namespace/allgemein">2.1.0.1.0</allgemein:BiPROVersion>
        </wst:RequestSecurityTokenResponse>
    </soapenv:Body>
</soapenv:Envelope>

是的,还有一个WSDL文件,但是Delphi的代码生成器并没有为里面的所有东西生成代码…… 生成的代码缺少两个相关的类型定义……而且不可能得到正确的 wsdl……所以我决定自己编写接口单元:

      BinarySecurityToken = class(TRemotable)
      private
        FEncodingType: string;
        FValueType: string;
        FVDGTicket: string;

      public
      published
        property EncodingType: string Index (IS_ATTR) read FEncodingType write FEncodingType;
        property ValueType: string Index (IS_ATTR) read FValueType write FValueType;
        property VDGTicket: string Index (IS_TEXT) read FVDGTicket write FVDGTicket;
      end;

      Security = class(TSoapHeader)
      private
        FBinarySecurityToken: BinarySecurityToken;
      public
        destructor Destroy; override;
      published
        property BinarySecurityToken: BinarySecurityToken Index (IS_REF) read FBinarySecurityToken write FBinarySecurityToken;
      end;

      TokenType = class(TRemotable)
      private
        FTokenType: string;
      public
      published
        property TokenType: string Index (IS_TEXT) read FTokenType write FTokenType;
      end;

      RequestType = class(TRemotable)
      private
        FRequestType: string;
      published
        property RequestType: string Index (IS_TEXT) read FRequestType write FRequestType;
      end;

      RequestSecurityToken = class(TRemotable)
      private
        FTokenType: TokenType;
        FRequestType: RequestType;
      public
        destructor Destroy; override;
      published
        property TokenType: TokenType Index (IS_REF) read FTokenType write FTokenType;
        property RequestType: RequestType Index (IS_REF) read FRequestType write FRequestType;
      end;

      Created = class(TRemotable)
      private
        FDate: TXSDateTime;
      public
        destructor Destroy; override;
      published
        property Date: TXSDateTime Index (IS_TEXT) read FDate write FDate;
      end;

      Expires = class(TRemotable)
      private
        FDate: TXSDateTime;
      public
        destructor Destroy; override;
      published
        property Date: TXSDateTime Index (IS_TEXT) read FDate write FDate;
      end;

      Lifetime = class(TRemotable)
      private
        FCreated: Created;
        FExpires: Expires;
      public
        destructor Destroy; override;
      published
        property Created: Created Index (IS_REF) read FCreated write FCreated;
        property Expires: Expires Index (IS_REF) read FExpires write FExpires;
      end;

      Identifier = class(TRemotable)
      private
        FSCTToken: string;
      public
      published
        property SCTToken: string Index (IS_TEXT) read FSCTToken write FSCTToken;
      end;

      SecurityContextToken = class(TRemotable)
      private
        FIdentifier: Identifier;
      public
        destructor Destroy; override;
      published
        property Identifier: Identifier Index (IS_REF) read FIdentifier write FIdentifier;
      end;

      RequestedSecurityToken = class(TRemotable)
      private
        FSecurityContextToken: SecurityContextToken;
      public
        destructor Destroy; override;
      published
        property SecurityContextToken: SecurityContextToken Index (IS_REF) read FSecurityContextToken write FSecurityContextToken;
      end;

      BiPROVersion = class(TRemotable)
      private
        FVersion: string;
      public
      published
        property Version: string Index (IS_TEXT) read FVersion write FVersion;
      end;

      RequestSecurityTokenResponse = class(TRemotable)
      private
        FTokenType: TokenType;
        FLifetime: Lifetime;
        FRequestedSecurityToken: RequestedSecurityToken;
        FBiPROVersion: BiPROVersion;
      public
        destructor Destroy; override;
      published
        property TokenType: TokenType Index (IS_REF) read FTokenType write FTokenType;
        property Lifetime: Lifetime Index (IS_REF) read FLifetime write FLifetime;
        property RequestedSecurityToken: RequestedSecurityToken Index (IS_REF) read FRequestedSecurityToken write FRequestedSecurityToken;
        property BiPROVersion: BiPROVersion Index (IS_REF) read FBiPROVersion write FBiPROVersion;
      end;

  SecurityTokenServicePortType = interface(IInvokable)
  ['{FE7EBD83-56D0-4542-5A4D-662805285ED8}']
    function  RequestSecurityToken(const TokenType: TokenType; RequestType: RequestType): RequestSecurityTokenResponse; stdcall;
  end;

    initialization
      { SecurityTokenServicePortType }
      InvRegistry.RegisterInterface(TypeInfo(SecurityTokenServicePortType), 'http://schemas.xmlsoap.org/ws/2005/02/trust', 'UTF-8');
      InvRegistry.RegisterDefaultSOAPAction(TypeInfo(SecurityTokenServicePortType), '');
      InvRegistry.RegisterInvokeOptions(TypeInfo(SecurityTokenServicePortType), ioDocument);
    //  InvRegistry.RegisterInvokeOptions(TypeInfo(SecurityTokenServicePortType), ioLiteral);
      { SecurityTokenServicePortType.RequestSecurityToken }
    //  InvRegistry.RegisterMethodInfo(TypeInfo(SecurityTokenServicePortType), 'RequestSecurityToken', '',
    //                                 '[RequestNS="http://schemas.xmlsoap.org/ws/2005/02/trust", ResponseNS="http://schemas.xmlsoap.org/ws/2005/02/trust"]');

    //  InvRegistry.RegisterParamInfo(TypeInfo(SecurityTokenServicePortType), 'RequestSecurityToken', 'RequestSecurityToken', '',
    //                                '[Namespace="http://schemas.xmlsoap.org/ws/2005/02/trust"]', IS_REF);
    //  InvRegistry.RegisterParamInfo(TypeInfo(SecurityTokenServicePortType), 'RequestSecurityToken', 'RequestSecurityTokenResponse', '',
    //                                '[Namespace="http://schemas.xmlsoap.org/ws/2005/02/trust"]', IS_REF);

      InvRegistry.RegisterMethodInfo(TypeInfo(SecurityTokenServicePortType), 'RequestSecurityToken', '',
                                     '[ReturnName="RequestSecurityTokenResponse", Namespace="http://schemas.xmlsoap.org/ws/2005/02/trust"]');
      InvRegistry.RegisterParamInfo(TypeInfo(SecurityTokenServicePortType), 'RequestSecurityToken', 'RequestSecurityTokenResponse', '',
                                    '[Namespace="http://schemas.xmlsoap.org/ws/2005/02/trust"]');

      RemClassRegistry.RegisterXSClass(BiPROVersion,
        'http://www.bipro.net/namespace/allgemein', 'BiPROVersion');
      RemClassRegistry.RegisterXSClass(Identifier,
        'http://schemas.xmlsoap.org/ws/2005/02/sc', 'Identifier');
      RemClassRegistry.RegisterXSClass(SecurityContextToken,
        'http://schemas.xmlsoap.org/ws/2005/02/sc', 'SecurityContextToken');
      RemClassRegistry.RegisterXSClass(RequestedSecurityToken,
        'http://schemas.xmlsoap.org/ws/2005/02/trust', 'RequestedSecurityToken');
      RemClassRegistry.RegisterXSClass(Created,
        'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd', 'Created');
      RemClassRegistry.RegisterXSClass(Expires,
        'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd', 'Expires');
      RemClassRegistry.RegisterXSClass(Lifetime,
        'http://schemas.xmlsoap.org/ws/2005/02/trust', 'Lifetime');

      RemClassRegistry.RegisterXSClass(RequestSecurityToken,
        'http://schemas.xmlsoap.org/ws/2005/02/trust', 'RequestSecurityToken');
      RemClassRegistry.RegisterXSClass(RequestSecurityTokenResponse,
        'http://schemas.xmlsoap.org/ws/2005/02/trust', 'RequestSecurityTokenResponse');

      RemClassRegistry.RegisterXSClass(RequestType,
        '', 'RequestType');
      RemClassRegistry.RegisterXSClass(TokenType,
        '', 'TokenType');
      RemClassRegistry.RegisterXSClass(BinarySecurityToken,
        'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd', 'BinarySecurityToken');
      RemClassRegistry.RegisterXSClass(Security,
        'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd', 'Security');

      InvRegistry.RegisterHeaderClass(TypeInfo(SecurityTokenServicePortType),
        Security, 'Security',
        'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd');

    end.

现在......这似乎工作...... delphi soap生成上述请求,将其发送到网络服务并接收响应......我已经检查过(将其保存到RIO.OnAfterExecute( ) 事件)。响应正常。

但我遇到了一个问题:RequestSecureToken (aTokenOut) 方法的结果是 nil 值。

procedure TMainForm.btnGetTheTicket2Click(Sender: TObject);
var
  aBean: SecurityTokenServicePortType;
  aTokenOut: RequestSecurityTokenResponse;
  aSCTHeader: SecurityTokenService_2.Security;
  aCreated: TDateTime;
  aExpires: TDateTime;
  aTicket: string;
  aTokenType: TokenType;
  aRequestType: RequestType;
begin
  aBean := SecurityTokenService_2.GetSecurityTokenServicePortType;

  aSCTHeader := SecurityTokenService_2.Security.Create;
  try
    aSCTHeader.BinarySecurityToken := SecurityTokenService_2.BinarySecurityToken.Create;
    aSCTHeader.BinarySecurityToken.EncodingType := 'NS1:Base64Binary';
    aSCTHeader.BinarySecurityToken.ValueType := 'bipro:VDGTicket';
    aSCTHeader.BinarySecurityToken.VDGTicket := edVDGTicket.Text;
    (aBean as ISOAPHeaders).Send(aSCTHeader);

    aTokenType := TokenType.Create;
    try
      aTokenType.TokenType := 'http://schemas.xmlsoap.org/ws/2005/02/sc/sct';
      aRequestType := RequestType.Create;
      try
        aRequestType.RequestType := 'http://schemas.xmlsoap.org/ws/2005/02/trust/Issue';

        aTokenOut := aBean.RequestSecurityToken(aTokenType, aRequestType);
        try

// place a breakpoint here 

          aCreated := aTokenOut.Lifetime.Created.Date.AsDateTime;
          aExpires := aTokenOut.Lifetime.Expires.Date.AsDateTime;

          aTicket := aTokenOut.RequestedSecurityToken.SecurityContextToken.Identifier.SCTToken;
        finally
          FreeAndnil(aTokenOut);
        end;
      finally
        FreeAndNil(aRequestType);
      end;
    finally
      FreeAndNil(aTokenType);
    end;
  finally
    FreeAndNil(aSCTHeader);
  end;
end;

我忘记注册什么了吗?我做错了什么吗?

Fallback:是否有可能从 request-xml 和 response-xml 生成 wsdl 文件?

【问题讨论】:

  • delphi 不生成整个 WSDL 是什么意思?
  • 可以,但是生成的代码不完整...缺少重要的类型定义...生成的代码无法编译。
  • 可能是 wsdl 已损坏...所以我尝试不使用它...
  • 什么是delphi版本?
  • 德尔福 XE10(西雅图)

标签: web-services delphi soap wsdl webservice-client


【解决方案1】:

问题是RequestSecurityToken方法的接口...

  SecurityTokenServicePortType = interface(IInvokable)
  ['{FE7EBD83-56D0-4542-5A4D-662805285ED8}']
    function RequestSecurityToken(const TokenType: TokenType; RequestType: RequestType): RequestSecurityTokenResponse; stdcall;
  end;

对于那种 SOAP-Response,它必须是这样的:

  SecurityTokenServicePortType = interface(IInvokable)
  ['{FE7EBD83-56D0-4542-5A4D-662805285ED8}']
    procedure RequestSecurityToken(TokenType: TokenType; RequestType: RequestType;
      out Lifetime: Lifetime;
      out RequestedSecurityToken: RequestedSecurityToken;
      out BiPROVersion: BiPROVersion); stdcall;
  end;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多