简体   繁体   中英

XML file upload with Authorization in header, error 401

I'm trying to send an XML file through the the TIdHTTP.Post() method. I saw many examples in the questions here on the site, but I have not found any that suit what I'm doing.

I need to first log in to the webservice and it returns me a SessionID and UserAuth , and then I need to send the XML file using this info.

Here's how I'm doing it:

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;

In the second POST, I get the response:

HTTP / 1.1 401 Unauthorized


The following is an excerpt from the documentation:

The URL where the description of the services can be seen is: https://svchomologacao.sigen.cidasc.sc.gov.br

which points to the CIDASC test database, so that companies providing IT services to pesticides, hereinafter referred to as EIS, may integration of its programs via WEB Services.

After the HIA integration is approved by CIDASC, the URL which will be used to send the official data will be: http://sigensvc.cidasc.sc.gov.br

where the prescriptions will be stored in the production database of CIDASC.

authToken is the combination (Encode) in BASE64 (www.base64encode.org) and in UTF-8, the login and password of the professional that issued the prescription separated by a colon (:) as below:

ex.: professionaluser: professionalpass

From the example above, the generated authToken would be: dXN1YXJpb2RvcHJvZmlzc2lvbmFsOnNlbmhhZG9wcm9maXNzaW9uYWw =

To establish the connection with the cidasc server, in order to transmission of the prescriptions of a particular EIS should call the Login method of the Access service, as shown below:

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

where xyz will be the token obtained in step 2.

We remember that this method is POST, so that it will only operate via a call made by the software being developed by the EIS. For testing, existing programs may be used to such as POSTMAN.

SEND THE RECIPIENTS TO CIDASC After establishing the connection to the server, the EIS should call the Include method of the Receipt service, to send the recipients, as shown below:

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

From this point on, the system developed by the EIS individually, that is, it transmits the first one and waits for the response code of the method.

After changing HTTPS it was like this:

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);

Now I get error:

10054 Connection Reset by Peer


I contacted the support by email, and they told me that The UserAuth and SessionId data must be sent in the header cookie of the include call, and sent an example in 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();
        }
    }
}

But I could not do the same in Delphi.

Based on the email you received from the server support team, you need to create HTTP cookies for the SessionID and UserAuth values, NOT create individual HTTP headers like you originally tried. Two completely different things.

You can use Indy's TIdCookieMananger component for this task, eg:

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM