簡體   English   中英

標題中包含授權的XML文件上傳,錯誤401

[英]XML file upload with Authorization in header, error 401

我正在嘗試通過TIdHTTP.Post()方法發送XML文件。 我在網站上的問題中看到了很多示例,但是沒有找到適合我正在做的事情的示例。

我需要先登錄到Web服務,它會返回一個SessionIDUserAuth ,然后我需要使用此信息發送XML文件。

這是我的做法:

var
  IdHTTP : TIdHTTP;
  params : TMemoryStream;
  vResponse : TStringStream;
  UserName, PassUser, URLogon, URSend, AuthUser: string;
  jsonObj, jSubObj: TJSONObject;
begin
  IdHTTP := TIdHTTP.Create;
  vResponse := TStringStream.Create('');
  params := TMemoryStream.Create;
  UserName := '123456';
  PassUser := '12345678';
  AuthUser := string(EncodeBase64(AnsiString(UserName+':'+PassUser)));
  URLogon := 'http://svchomologacao.sigen.cidasc.sc.gov.br/Acesso/Login?authToken=' + AuthUser;
  URSend := 'http://svchomologacao.sigen.cidasc.sc.gov.br/Receituario/Incluir';

  IdHTTP.Post(URLogon, params, vResponse);
  Memo1.Lines.Add(vResponse.DataString);

  //this is the return I get from WS, the SessionID and UserAuth in JSon:
  jsonObj := TJsonObject.ParseJSONValue(vResponse.DataString) as TJsonObject; //Json conversion

  params.LoadFromFile('D:\Exemple.xml');

  IdHTTP.Request.CustomHeaders.Clear;
  IdHTTP.Request.Clear;
  IdHTTP.ConnectTimeout := 30000;
  IdHTTP.Request.BasicAuthentication := True;
  IdHTTP.Request.ContentType := 'application/xml';
  IdHTTP.Request.ContentEncoding := 'raw';
  IdHTTP.Request.Accept := 'application/xml';
  IdHTTP.Response.CharSet := 'UTF-8';
  IdHTTP.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; GTB5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; Maxthon; InfoPath.1; .NET CLR 3.5.30729; .NET CLR 3.0.30618)';
  IdHTTP.Request.CustomHeaders.AddValue(jsonObj.Get(0).JsonString.Value, jsonObj.Get(0).JsonValue.Value);
  IdHTTP.Request.CustomHeaders.AddValue(jsonObj.Get(1).JsonString.Value, jsonObj.Get(1).JsonValue.Value);

  IdHTTP.Post(URSend, params, vResponse);
  ShowMessage(vResponse.DataString);
end;

在第二個POST中,得到響應:

HTTP / 1.1 401未經授權


以下是文檔摘錄:

可以看到服務描述的URL是: https : //svchomologacao.sigen.cidasc.sc.gov.br

指向CIDASC測試數據庫,以便向農葯提供IT服務的公司(以下稱為EIS)可以通過WEB服務集成其程序。

在CIDASC批准HIA集成后,將用於發送官方數據的URL為: http ://sigensvc.cidasc.sc.gov.br

處方將存儲在CIDASC的生產數據庫中。

authToken是BASE64(www.base64encode.org)和UTF-8中的組合(編碼),UTF-8是發布處方的專業人員的登錄名和密碼,並用冒號(:)分隔,如下所示:

例如:professionaluser:professionalpass

在上面的示例中,生成的authToken將為:dXN1YXJpb2RvcHJvZmlzc2lvbmFsOnNlbmhhZG9wcm9maXNzaW9uYWw =

要建立與cidasc服務器的連接,為了傳輸特定EIS的處方,應調用Access服務的Login方法,如下所示:

svchomologacao.sigen.cidosc.sc.gov.br/Acesso/Login?authToken=xyz

其中xyz是在步驟2中獲得的令牌。

我們記得該方法是POST,因此它只能通過EIS正在開發的軟件進行的調用來操作。 為了進行測試,可以使用現有程序,例如POSTMAN。

將收件人發送到CIDASC建立與服務器的連接后,EIS應調用收據服務的Include方法來發送收件人,如下所示:

svchomologacao.sigen.cidasc.sc.gov.br/Receituario/Incluir

從這一點開始,EIS單獨開發的系統,即,它發送第一個系統並等待該方法的響應代碼。

更改HTTPS后,它是這樣的:

var
  IdHTTP : TIdHTTP;
  sshSocketHandler: TIdSSLIOHandlerSocketOpenSSL;
  vResponse : TStringStream;
  params : TMemoryStream;
begin
  IdHTTP := TidHTTP.Create;
  sshSocketHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
  sshSocketHandler.SSLOptions.Method := sslvSSLv2;
  IdHTTP.IOHandler := sshSocketHandler;
  params := TMemoryStream.Create;
  vResponse := TStringStream.Create('');

  IdHTTP.Post('https://svchomologacao.sigen.cidasc.sc.gov.br/Acesso/Login?authToken=MzQ3MjA1Mzk2OjM4MjY1OTk5', params, vResponse);
  Memo1.Lines.Add(vResponse.DataString);

現在我收到錯誤:

10054對等連接重置


我通過電子郵件聯系支持人員,他們告訴我必須在include調用的標頭Cookie中發送UserAuth和SessionId數據,並在C#中發送示例:

public void InvokeService(string xml){


    HttpWebRequest requestReceituarioCancelar = (
        HttpWebRequest)WebRequest.CreateHttp(
        @"https://svchomologacao.sigen.cidasc.sc.gov.br/Receituario/Cancelar"
    );

    requestReceituarioCancelar.Headers.Clear();
    requestReceituarioCancelar.ContentType = "application/xml;charset=\"utf-8\"";
    requestReceituarioCancelar.Accept = "application/xml";
    requestReceituarioCancelar.Method = "POST";

    XmlDocument SOAPReqBody = new XmlDocument();

    //ServiceResult: contains the login return (SessionID and UserAuth)

    var ServiceResult = StreamReceituarioLogin(requestLogin);

    var uri = new Uri("https://svchomologacao.sigen.cidasc.sc.gov.br");

    //Converts login return to json
    var retorno = JsonConvert.DeserializeObject<StructCookie>(ServiceResult); 

    //In the CookieContainer add the Uri containing the URL, SessionID and UserAuth 

    requestReceituarioCancelar.CookieContainer = new CookieContainer();
    requestReceituarioCancelar.CookieContainer.Add(uri, new Cookie("SessionID", retorno.SessionID));
    requestReceituarioCancelar.CookieContainer.Add(uri, new Cookie("UserAuth", retorno.UserAuth)); 

    SOAPReqBody.LoadXml(m);

    //Now it sends the requestReceituarioCancelar and the SOAPReqBody containing the XML
    Stream stream = null;
    using (stream = requestReceituarioCancelar.GetRequestStream())
    {
        SOAPReqBody.Save(stream);
        stream.Close();
    }
    using (WebResponse Serviceres = requestReceituarioCancelar.GetResponse())
    {
        using (StreamReader rd = new StreamReader(Serviceres.GetResponseStream()))
        {
            var ServiceResult = rd.ReadToEnd();
            rd.Close();
        }
    }
}

但是我不能在Delphi中做同樣的事情。

根據您從服務器支持團隊收到的電子郵件,您需要為SessionIDUserAuth值創建HTTP cookie ,而不是像最初嘗試的那樣創建單獨的HTTP標頭 兩件完全不同的東西。

您可以將Indy的TIdCookieMananger組件用於此任務,例如:

var
  IdHTTP : TIdHTTP;
  sshSocketHandler: TIdSSLIOHandlerSocketOpenSSL;
  params : TMemoryStream;
  Response : string;
  UserName, PassUser, URLogon, URSend, URCookie, AuthUser: string;
  jsonObj: TJSONObject;
  Uri: TIdUri;
begin
  IdHTTP := TIdHTTP.Create;
  try
    sshSocketHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdHTTP);
    sshSocketHandler.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
    IdHTTP.IOHandler := sshSocketHandler;

    IdHTTP.CookieManager := TIdCookieManager.Create(IdHTTP);
    IdHTTP.AllowCookies := True;

    UserName := '123456';
    PassUser := '12345678';
    AuthUser := string(EncodeBase64(AnsiString(UserName+':'+PassUser)));

    URLogon := 'https://svchomologacao.sigen.cidasc.sc.gov.br/Acesso/Login?authToken=' + AuthUser';
    URSend := 'https://svchomologacao.sigen.cidasc.sc.gov.br/Receituario/Incluir';
    URCookie := 'https://svchomologacao.sigen.cidasc.sc.gov.br';

    params := TMemoryStream.Create;
    try
      Response := IdHTTP.Post(URLogon, params);
      Memo1.Lines.Add(Response);

      //this is the return I get from WS, the SessionID and UserAuth in JSon:
      jsonObj := TJsonObject.ParseJSONValue(Response) as TJsonObject; //Json conversion
      try
        Uri := TIdUri.Create(URCookie);
        try
          IdHTTP.CookieManager.AddServerCookie('SessionID=' + jsonObj.Values['SessionID'].Value, Uri);
          IdHTTP.CookieManager.AddServerCookie('UserAuth=' + jsonObj.Values['UserAuth'].Value, Uri);
        finally
          Uri.Free;
        end;
      finally
        jsonObj.Free;
      end;

      params.LoadFromFile('D:\Exemple.xml');

      IdHTTP.Request.Clear;
      IdHTTP.ConnectTimeout := 30000;
      IdHTTP.Request.Accept := 'application/xml';
      IdHTTP.Request.ContentType := 'application/xml';
      IdHTTP.Request.CharSet := 'utf-8';
      IdHTTP.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; GTB5; Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1) ; Maxthon; InfoPath.1; .NET CLR 3.5.30729; .NET CLR 3.0.30618)';

      Response := IdHTTP.Post(URSend, params);
      ShowMessage(Response);
    finally
      params.Free;
    end;
  finally
    IdHTTP.Free;
  end;
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM