标题中带有授权的XML文件上传,错误401

时间:2019-03-11 21:09:34

标签: delphi post http-status-code-401 idhttp

我正在尝试通过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中做同样的事情。

0 个答案:

没有答案