首页 > 解决方案 > 在 C# Visual Studio ERCOT 上使用 Signed SOAP 发出 Web 请求

问题描述

我在使用 SSL 证书身份验证从 C# 代码向外部 Web 服务发出请求时遇到问题。目前,我从该 Web 服务收到错误代码 500 Internal Server Error 作为响应。我与外部服务团队进行了讨论,他们建议我将请求作为签名 SOAP 请求发送。服务器期待证书详细信息,因此我尝试将其作为签名的 SOAP 请求发送。我试图将它添加为 Visual Studio 中的服务引用,但我在那儿遇到错误,Reference.cs 没有生成。所以我打算创建一个包含证书详细信息的 SOAP 请求。但我面临难以在“wsse:Security”标签中生成内容,如 DigestValue、SignatureValue 等。

SOAP 请求:

<SOAP-ENV:Envelope xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsu="http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsse="http://www.docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:mes="http://www.ercot.com/schema/2007-06/nodal/ews/message">
  <SOAP-ENV:Header>
    <wsse:Security SOAP-ENV:mustUnderstand="1">
      <wsse:BinarySecurityToken
      EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
        ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"
        wsu:Id="CertId-1776694">
        MIIGdDCCBVygAwIBAgIQLReBpu3QZi2DsveIdW4fljANBgkqhkiG9w0BAQsFADBm
        MQswCQYDVQQGEwJVUzE0MDIGA1UEChMrRWxlY3RyaWMgUmVsaWFiaWxpdHkgQ291
        bmNpbCBvZiBUZXhhcywgSW5jLjEhMB8GA1UEAxMYRVJDT1QgRW50ZXJwcmlzZSBU
        RVNUIENBMB4XDTIxMDYxNjAwMDAwMFoXDTIyMDYxNjIzNTk1OVowggE3MTQwMgYD
        BzABhhtodHRwOi8vcGtpLW9jc3Auc3ltYXV0aC5jb20wgccGCCsGAQUFBzAChoG6
        bGRhcDovL2RpcmVjdG9yeS5zeW1hdXRoLmNvbS9DTiUyMCUzRCUyMEVSQ09UJTIw
        RW50ZXJwcmlzZSUyMFRFU1QlMjBDQSUyQyUyME8lMjAlM0QlMjAlMjJFbGVjdHJp
        YyUyMFJlbGlhYmlsaXR5JTIwQ291bmNpbCUyMG9mJTIwVGV4YXMlMkMlMjBJbmMu
        JTIyJTJDJTIwQyUyMCUzRCUyMFVTP2NBQ2VydGlmaWNhdGU7YmluYXJ5MB8GA1Ud
        IwQYMBaAFM9vgLFH3rW5jzTpa58gBemf5RwPMCwGCmCGSAGG+EUBEAMEHjAcBhJg
        hkgBhvhFARABAgMEAZTtjgwWBjQ1MDY3NzA5BgpghkgBhvhFARAFBCswKQIBABYk
        YUhSMGNITTZMeTl3YTJrdGNtRXVjM2x0WVhWMGFDNWpiMjA9MA0GCSqGSIb3DQEB
        CwUAA4IBAQB/dbBM3+r8efvt4hGsBhm4gTBqdCG5Gs1zyv4q6tJA2gAokc0QA2f/
        JWBBE1q1iT7f4b9H8yd/dwL2r8LWeCNbKLF7tifYXcC7avgb72FZgiK2bLSYS3Mz
        JtMBcm/hduVHEIhsk+ZFBsQHjIeFnDEANoMOK3A40F3KzsUjg2RG/6G5r9VNcLcv
        rGWATaR6P1s419rdNk1Yr+0mDwchek40s1avn5uMNQAUQDeZgF+L5+OFIzSSjnp6
        p+Ee1dXwmOIASirs3PD43tb/hX5X2Mj4YRuPClnLJXRHGyeVwX3VRaz3YLOXtcsp
        bb7L0aTroePv1U8CXRvQpWbDuApf8jz1
      </wsse:BinarySecurityToken>
      <ds:Signature>
        <ds:SignedInfo>
          <ds:CanonicalizationMethod
            Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
          <ds:SignatureMethod
           Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
          <ds:Reference URI="#id-1464350">
            <ds:Transforms>
              <ds:Transform
                Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
            </ds:Transforms>
            <ds:DigestMethod
        Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>
              1JmC1C0FrlPB42xfFKolgaCew5kdedssd=
            </ds:DigestValue>
          </ds:Reference>
          <ds:Reference URI="#id-13498124">
            <ds:Transforms>
              <ds:Transform
                Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
              <wsse:TransformationParameters>
                <ds:CanonicalizationMethod
                Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
              </wsse:TransformationParameters>
              </ds:Transform>
            </ds:Transforms>
            <ds:DigestMethod
         Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
            <ds:DigestValue>
              sEaCJjrObpDVfM8zcvbcbuabwQdBGKbYdssf=
            </ds:DigestValue>
          </ds:Reference>
        </ds:SignedInfo>
        <ds:SignatureValue>
          H1b7jH2bHpbrzJXkFS0msdUYsEaCJjrObycDMH4n6m4oTRtbo4Yk35/JzGcuwUYZ3vfdgvdvc          AwPcnqmcP5ROshjJparaPGuvQhbFR7zCxet2aoawJFWgG8jIeuDZDE8y6n+kbBzxadF2tGN8/nH6IlKg0+onD09i81rPHDAa 2kstCclX2NDet1Rnmfs=
        </ds:SignatureValue>
        <ds:KeyInfo>
          <wsse:SecurityTokenReference wsu:Id="id-13498124">
            <wsse:Reference URI="#CertId-1776694" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
          </wsse:SecurityTokenReference>
        </ds:KeyInfo>
      </ds:Signature>
    </wsse:Security>
  </SOAP-ENV:Header>
  <SOAP-ENV:Body wsu:Id="id-1464350">
    <mes:RequestMessage
 xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema"
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
 xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wsswssecurity-utility-1.0.xsd"
 xmlns="http://www.ercot.com/schema/2007-06/nodal/ews/message">
      <mes:Header>
        <mes:Verb>get</mes:Verb>
        <mes:Noun>Reports</mes:Noun>
        <mes:ReplayDetection>
          <wsu:Created>
            2021-6-16
          </wsu:Created>
          <wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">
            75753793-50c2-455b-a9b3-123cb26474cxze7
          </wsse:Nonce>
        </mes:ReplayDetection>
        <mes:Source>Test123</mes:Source>
        <mes:UserID>API_APITEST</mes:UserID>
      </mes:Header>
      <mes:Request>
        <mes:Option>11111</mes:Option>
      </mes:Request>
      <mes:Payload>
        <mes:Reports xmlns:mes="http://www.ercot.com/schema/2007-06/nodal/ews">
          <mes:Report>
              <mes:operatingDate>2021-6-16</mes:operatingDate>
              <mes:reportGroup>60 Day Disclosure</mes:reportGroup>
              <mes:fileName>rpt.00010029.0000000000000000.20091216.093316.dummy_file.zip</mes:fileName>
              <mes:created>2009-12-16T09:33:16</mes:created>
              <mes:size>1412</mes:size>
              <mes:format>zip</mes:format>
              <mes:URL>https://Host:Port/folder/?doclookupId=32423</mes:URL>
            </mes:Report>
        </mes:Reports>
      </mes:Payload>
    </mes:RequestMessage>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

生成请求对象并调用它的 C# 代码:

public class ERCOTWebRequest
    {
        
        string action = @"https://testmisapi.ercot.com/2007-08/Nodal/eEDS/EWS?MarketInfo";

        public bool GetReports()
        {
            try
            {
                // WebRequestHelper.
                var request = CreateSOAPWebRequest();


                XmlDocument SOAPReqBody = new XmlDocument();
                //SOAP Body Request  
                string nodalXml = File.ReadAllText(@"C:\Users\test\source\repos\WebRequestHelper\ERCOTWebServiceHelper\XMLFile1.xml");

   //             nodalXml = @"<?xml version=""1.0"" encoding=""utf-8""?>  
   //         <soapenv:Envelope xmlns:soapenv=""http://schemas.xmlsoap.org/soap/envelope/"" xmlns:mes=""http://www.ercot.com/schema/2007-06/nodal/ews/message"">
   //<soapenv:Header/>
   // <soapenv:Body>
   // " + nodalXml + @"
   //             </soapenv:Body>  
   //         </soapenv:Envelope>";

                SOAPReqBody.LoadXml(nodalXml);

                using (Stream stream = request.GetRequestStream())
                {
                    SOAPReqBody.Save(stream);
                }
                
                //Geting response from request  
                using (WebResponse Serviceres = request.GetResponse())
                {
                    using (StreamReader rd = new StreamReader(Serviceres.GetResponseStream()))
                    {
                        //reading stream  
                        var ServiceResult = rd.ReadToEnd();
                        //writting stream result on console  
                        Console.WriteLine(ServiceResult);
                        Console.ReadLine();
                    }
                }

                return true;
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }
        }

        public HttpWebRequest CreateSOAPWebRequest()
        {
            string host = @"https://testmisapi.ercot.com/2007-08/Nodal/eEDS/EWS/";
            string certName = @"C:\Users\Test\Downloads\ERCOT_TEST_CA\TestAPI123.pfx";
            string password = @"password";
            
            ServicePointManager.Expect100Continue = true;
            ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

            X509Certificate2Collection certificates = new X509Certificate2Collection();
            certificates.Import(certName, password, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);

            ServicePointManager.ServerCertificateValidationCallback = (a, b, c, d) => true;
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(host);
            req.AllowAutoRedirect = true;
            req.ClientCertificates = certificates;
            req.ContentType = "text/xml;charset=\"utf-8\"";
            req.Accept = "text/xml";
            req.Headers.Add("SOAPAction", action);
            req.Proxy = WebRequest.GetSystemWebProxy();
            //HTTP method    
            req.Method = "POST";
            return req;
        }
    }

目前我在尝试发出 SOAP 请求时遇到错误(错误 500:内部服务器错误)。有人请帮忙。

标签: c#visual-studioweb-servicessoapwsdl

解决方案


我在尝试使用 ERCOT API 时遇到了同样的问题,但我注意到 Postman 能够返回比 HTTP 500 内部服务器错误更多的信息。尝试在异常处理中添加类似这样的内容,以从响应流中获取详细信息:

        catch (WebException webEx)
        {
            if (webEx.Status.Equals(WebExceptionStatus.ProtocolError))
            {
                HttpWebResponse webResp = (HttpWebResponse)webEx.Response;
                string respText = (new StreamReader(webResp.GetResponseStream())).ReadToEnd();
                LogError("error in EntryPoint: " + webResp.StatusDescription);
                LogError("output = " + respText);
            }
        }

推荐阅读