HTTP / 1.1 400错误请求 - 基于WS安全性的SOAP消息UsernameToken Profile 1.1,WS-I Basic Profile 1.1

时间:2017-11-06 15:07:39

标签: security authentication soap token

首先,我编写了soap信封,其中包含原始XML文件。肥皂信封使用以下代码制作:

procedure MakeSoapEnvelope(FileNameIn: AnsiString);
Const
  SpCon = 0;
  MINPERDAY = 1440;
  SourceFile = 'XMLFILE';
  TargetFile = 'SOAPENVELOP';
Var
  AStr, Bapi_Versie_Pen_Soap, StrType: AnsiString;
  uNow: _SystemTime;
  dtNow: TDateTime;
  sNow: String;
  FSource, FDest : System.Text;

  function FillTag(TagIn, FillPart:AnsiString) : AnsiString;
  var
    HTr: Integer;
  begin
    Result := NulStr;
    for HTr := 1 to Length(TagIn) do
    begin
      if (HTr = Length(TagIn)) then //direct voor laatste positie invoegen
        Result := Result + Spatie + FillPart;
      Result := Result + TagIn[HTr];
    end;
  end; {func FillTag}

  procedure FDestAdd(SpIn : Integer; TagIn, VeldIn, FillIn : AnsiString);
  begin
    if (FillIn = NulStr) then
    begin
      WriteLn(FDest, Spatie:(SpIn * AuditSpatieMarge), TagIn, VeldIn, EndTag(TagIn));
    end else
    begin
      Write(FDest, Spatie:(SpIn * AuditSpatieMarge));
      Write(FDest, FillTag(TagIn, FillIn));
      Write(FDest, VeldIn);
      Write(FDest, EndTag(TagIn));
      WriteLn(FDest, NulStr);
    end;
  end; {proc FDestAdd}

  function GenerateTimestampId : AnsiString;
  var
    IntUit : Integer;
  begin
    IntUit := 1 + Random(100);
    Result := '"_' + ItoSNulZonderPunten(IntUit) + '"';
  end; {func GenerateTimestampId}

  function MaakGUID : AnsiString;
  var
    Uid: TGuid;
  begin
    CreateGuid(Uid);
    Result := (GuidToString(Uid));
    //verwijderen accolades
    Result := VerwijderEnkelTeken(Result, '{');
    Result := VerwijderEnkelTeken(Result, '}');
  end; {func MaakGUID}

  function GenerateUserNameTokenId : AnsiString;
  begin
    Result := MaakGUID;
    Result := '"' + Result + '"';
  end; {func GenerateUserNameTokenId}

begin {procedure MakeSoapEnvelope}

  { start reserve file }
  AssignFile(FDest, TargetFile);
  Rewrite(FDest);

  //prepare SoAP-envelope-header
  WinApi.Windows.GetSystemTime(uNow);
  dtNow := SysUtils.SystemTimeToDateTime(uNow);
  sNow := FormatDateTime('yyyy-mm-dd"T"hh:mm:ss"Z"', dtNow);

  //write SoAP-envelope-header
  Bapi_Versie_Pen_Soap := Bapi_Versie_PenSoap_UPA_AGH;
  WriteLn(FDest, {Spatie:(0 * AuditSpatieMarge),} Bapi_Versie_Pen_Soap);
  WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), Xml_PA_Alg_Soap_Header_Start);
  WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_AGH_Security_Start);
  WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), FillTag(Xml_PA_Upa_AGH_Timestamp, Xml_PA_Upa_AGH_Id + GenerateTimestampId));
  WriteLn(FDest, Spatie:(4 * AuditSpatieMarge), Xml_PA_Upa_AGH_Created, FormatDateTime('yyyy-mm-dd"T"hh:mm:ss"Z"', dtNow), EndTag(Xml_PA_Upa_AGH_Created));
  WriteLn(FDest, Spatie:(4 * AuditSpatieMarge), Xml_PA_Upa_AGH_Expires, FormatDateTime('yyyy-mm-dd"T"hh:mm:ss"Z"', dtNow + 5 /MINPERDAY), EndTag(Xml_PA_Upa_AGH_Expires));
  WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), EndTag(Xml_PA_Upa_AGH_Timestamp));
  WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), FillTag(Xml_PA_Upa_UsernameToken_Start, Xml_PA_Upa_AGH_Id + GenerateUserNameTokenId));
  FDestAdd(4, Xml_PA_Upa_Username, XmlSendDlg.MeUserName.Text, NulStr);
  FDestAdd(4, Xml_PA_Upa_Password, TranslateTo64Base(XmlSendDlg.MePassword.Text), Xml_PA_Upa_AGH_Password_Type);
  WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), EndTag(Xml_PA_Upa_UsernameToken_Start));
  WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_Security_Stop);
  WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_AGH_To);
  WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_AGH_Action);
  WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), Xml_PA_Alg_Soap_Header_Stop);
  WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), Xml_PA_Alg_Soap_Body_Start);
  WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), Xml_PA_Upa_ZendBerichtAlsZIP_Start);
  FDestAdd(3, Xml_PA_Upa_idLcr, Bepaal_Upa_IdLcr, NulStr);
  FDestAdd(3, Xml_PA_Upa_idBer, XmlSendDlg.OrIdBericht, NulStr);
  WriteLn(FDest, Spatie:(3 * AuditSpatieMarge), Xml_PA_Upa_berichtZIP_Start);

  { open original xml file }
  SourceFile := FileNameIn;
  {$I-}
  AssignFile(FSource, SourceFile);
  Reset(FSource);
  { incorporate original xml file in soapenvelope}
  while not Eof(FSource) do
  begin
    ReadLn(FSource, AStr);
    WriteLn(FDest, Spatie:(4 * AuditSpatieMarge), AStr);
  end;
  CloseFile(FSource);

  {add endtag xml file in soapenvelope}
  WriteLn(FDest, 3 * AuditSpatieMarge,     EndTag(Xml_PA_Upa_berichtZIP_Start));
  WriteLn(FDest, Spatie:(2 * AuditSpatieMarge), EndTag(Xml_PA_Upa_ZendBerichtAlsZIP_Start));

  {write end soap-envelope }
  WriteLn(FDest, Spatie:(1 * AuditSpatieMarge), EndTag(Xml_PA_Alg_Soap_Body_Start));
  WriteLn(FDest, {Spatie:(0 * AuditSpatieMarge),} Xml_PA_Alg_Soap_Envelope_Einde);

  CloseFile(FDest);

  { save nieuwe file op in oude file }
  RenameResFile(SourceFile, TargetFile);
  {$I+}
end; { func MakeSoapEnvelope }

请注意:我不确定转换为Base64的MePassword.Text是否足以支持WS Security。

在此之后,肥皂信封看起来像这样:

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <soapenv:Header>
    <wsse:Security soapenv:mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsu:Timestamp wsu:Id="_83">
        <wsu:Created>2017-11-06T12:29:14Z</wsu:Created>
        <wsu:Expires>2017-11-06T12:34:14Z</wsu:Expires>
      </wsu:Timestamp>
      <wsse:UsernameToken wsu:Id="C2F32D7E-805F-466C-BD2B-FB0B28C01E24">
        <wsse:Username>MeUsername.Text</wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">This line represents the MePassword.Text in 64Base</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
    <To soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">https://localhost:44300/UPAWebService.svc</To>
    <Action soapenv:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://www.pensioenfederatie.nl/uniformePensioenAangifte/2015/05/WS/UPAWebService/ZendBerichtAlsZIP</Action>
  </soapenv:Header>
  <soapenv:Body>
    <ws:ZendBerichtAlsZIP>
      <ws:idLcr>A95972643</ws:idLcr>
      <ws:idBer>CLIENT-PA-01A-20171106132913</ws:idBer>
      <ws:berichtZIP>This line represents the original xml-file</ws:berichtZIP>
    </ws:ZendBerichtAlsZIP>

使用以下代码发送soap信封:

procedure Send_HTTP;
var
  XMLFileStream : TFileStream;
begin  {procedure Send_HTTP}
  XMLFileStream := TFileStream.Create(XmlSendDlg.XmlFileIn, fmOpenRead Or fmShareDenyWrite);
  Try
    IdHTTP1.HandleRedirects := True;
    IdHTTP1.HTTPOptions := [hoInProcessAuth, hoKeepOrigProtocol, hoForceEncodeParams];
    IdHTTP1.IoHandler.Port := Port_HTTPS;
    IdHTTP1.Request.ContentType := 'text/xml';
    IdHTTP1.Request.CharSet := 'utf-8';
    IdHTTP1.Request.Username := MeUsername.Text;
    IdHTTP1.Request.Password := MePassword.Text;
    IdHTTP1.Request.BasicAuthentication := False;//True;
    IdHTTP1.ReadTimeout := ReadTimeoutConst;
    IdHTTP1.Request.CustomHeaders.Clear;
    IdHTTP1.Request.CustomHeaders.Add('SOAPAction: "' + MeSoapAction.Text + '"');
    Try
      ReturnStr := IdHTTP1.Post(MeWebSite.Text, XMLFileStream);
    Except
      On E: Exception Do
      begin
        Memo1.Lines.Add('Fout: ' + E.Message);
      end;
    end;
    IdHTTP1.Disconnect;
  Finally
    XMLFileStream.Free;
  end;
end; {proc Send_HTTP}

发送肥皂信封会产生HTTP/1.1 400 Bad Request响应。收到的完整信息是:

HTTP/1.1 400 Bad Request
Cache-Control: private,no-cache, no-store, must-revalidate
Server: Microsoft-IIS/8.5
X-AspNet-Version: 4.0.30319
Strict-Transport-Security: max-age=31536000
X-FRAME-OPTIONS: SAMEORIGIN
X-Content-Type-Options: nosniff
Date: Mon, 06 Nov 2017 12:29:15 GMT
Content-Length: 0

出了什么问题?

0 个答案:

没有答案