简体   繁体   English

标题中包含授权的XML文件上传,错误401

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

I'm trying to send an XML file through the the TIdHTTP.Post() method. 我正在尝试通过TIdHTTP.Post()方法发送XML文件。 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. 我需要先登录到Web服务,它会返回一个SessionIDUserAuth ,然后我需要使用此信息发送XML文件。

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: 在第二个POST中,得到响应:

HTTP / 1.1 401 Unauthorized HTTP / 1.1 401未经授权


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 可以看到服务描述的URL是: 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. 指向CIDASC测试数据库,以便向农药提供IT服务的公司(以下称为EIS)可以通过WEB服务集成其程序。

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 在CIDASC批准HIA集成后,将用于发送官方数据的URL为: http ://sigensvc.cidasc.sc.gov.br

where the prescriptions will be stored in the production database of CIDASC. 处方将存储在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: authToken是BASE64(www.base64encode.org)和UTF-8中的组合(编码),UTF-8是发布处方的专业人员的登录名和密码,并用冒号(:)分隔,如下所示:

ex.: professionaluser: professionalpass 例如:professionaluser:professionalpass

From the example above, the generated authToken would be: dXN1YXJpb2RvcHJvZmlzc2lvbmFsOnNlbmhhZG9wcm9maXNzaW9uYWw = 在上面的示例中,生成的authToken将为: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: 要建立与cidasc服务器的连接,为了传输特定EIS的处方,应调用Access服务的Login方法,如下所示:

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

where xyz will be the token obtained in step 2. 其中xyz是在步骤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. 我们记得该方法是POST,因此它只能通过EIS正在开发的软件进行的调用来操作。 For testing, existing programs may be used to such as POSTMAN. 为了进行测试,可以使用现有程序,例如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: 将收件人发送到CIDASC建立与服务器的连接后,EIS应调用收据服务的Include方法来发送收件人,如下所示:

svchomologacao.sigen.cidasc.sc.gov.br/Receituario/Incluir 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. 从这一点开始,EIS单独开发的系统,即,它发送第一个系统并等待该方法的响应代码。

After changing HTTPS it was like this: 更改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);

Now I get error: 现在我收到错误:

10054 Connection Reset by Peer 10054对等连接重置


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 #: 我通过电子邮件联系支持人员,他们告诉我必须在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();
        }
    }
}

But I could not do the same in Delphi. 但是我不能在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. 根据您从服务器支持团队收到的电子邮件,您需要为SessionIDUserAuth值创建HTTP cookie ,而不是像最初尝试的那样创建单独的HTTP标头 Two completely different things. 两件完全不同的东西。

You can use Indy's TIdCookieMananger component for this task, eg: 您可以将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