2017-11-03 5 views
1

이 질문은 오래된 기술을 의미한다는 것을 알고 있습니다. 나는 벤더 시스템을 부르고 서비스를 변경할 능력이 없다. 우리는 XML/SOAP WS를 호출 한 다음 요청에 서명해야합니다. 10 년 전 WSE (Web Services Enhancements) 3.0과 같은 것을 사용했을 것입니다. 현재와 ​​같이 .Net Core (.Net Standard 2.0) 응용 프로그램에서 무엇을해야할지 고민 중입니다..Net Core의 서명이 필요한 XML SOAP 서비스를 어떻게 호출합니까?

상업용 솔루션을 비롯하여 다양한 종류의 솔루션을 기꺼이 사용할 수 있습니다. 나는 Chilkat를 보았다. 그러나 우리가 그것을 사용하기에는 너무 많이 포기하고있는 것처럼 보였다.

그들은 내가 언급하고있는 점에 대한 적절한 예를 가지고 있습니다. ,

<?xml version="1.0" encoding="UTF8" ?> 
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"> 
    <SOAP-ENV:Header> 
     <wsse:Security xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" 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#X509" wsu:Id="x509cert00">MIIDgzCCAmugAwIBAgIBADANBgkqhkiG9w0BAQUFADBcMRUwEwYDVQQDDAxUZXN0 
IENvbXBhbnkxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYD 
VQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTcwOTEzMDA1NTM1WhcN 
MTgwOTEzMDA1NTM1WjBcMRUwEwYDVQQDDAxUZXN0IENvbXBhbnkxCzAJBgNVBAYT 
AkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn 
aXRzIFB0eSBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDiWRKl 
x+88u4SKZnfCMraqMsfJCs6tcz3EjMYTWmRKhhUOE9pDkvZfv0mgF7pNHsTKvFRt 
oVnEVQaZC5TlHNOGa2QWit9YuruWjW8VSaU4s9gR1/Cg9/Zc8Z0yUEDpsaVnwuoA 
RpVzvzoRzPmTNpMNEcQ07aBjHP7OJrwyvcdqQA1BbfDVMmRmw1d+/i8tyR3cTyzl 
/3TismN5nrmhGh/ZF75FFA/xDN7PbVYDPowiFnEVHiBrYh2mFTabRUnb7K4oLx+d 
1L5x3Az299F/HYZlBenXpJLtnCL3+HY6qsGXVbzKjlKNqbXsmlzVkChu093weN/q 
UvWO2883cEiXmdqxAgMBAAGjUDBOMB0GA1UdDgQWBBRsMy2bxsCKYyUYtTYz/zZb 
z7Le0zAfBgNVHSMEGDAWgBRsMy2bxsCKYyUYtTYz/zZbz7Le0zAMBgNVHRMEBTAD 
AQH/MA0GCSqGSIb3DQEBBQUAA4IBAQBnFQ+Sc3s8y79DTsA7CvvAFeG/zvWQiu8y 
UM5LO1QcWeQQj29GMThqrY21dNfkynl7mZUMEeXKvwwzweFCc2odiUPHxoV1G4FE 
tzNaZ8Ap9jye78YQ8SB8NPQwC7ovecfSqNflT4NMAThSuxpGp8Ugf7a24LXozLzL 
bCRvG9sLGyRneZbfU8B43ELRLCkjzWR32N7D2pmKk4CEMiW0ScphU1JEHaimneMa 
TFc63hNzKpuj7+BGv4ZuvB1j/Mbmz53PGgFKnGQHPb2TIvMxyB+lML5vE0Bm8YWt 
P8DNyx11CCCdBdMWfeta6MjmmqcV5/YEq92c5O2Ql94tWFNLR6wQ</wsse:BinarySecurityToken> 
      <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> 
       <ds:SignedInfo> 
        <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"> 
         <InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="wsse SOAP-ENV" /> 
        </ds:CanonicalizationMethod> 
        <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> 
        <ds:Reference URI="#TheBody"> 
         <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>VhsSnaEAFsY0OYegKQh99v9csXg=</ds:DigestValue> 
        </ds:Reference> 
       </ds:SignedInfo> 
       <ds:SignatureValue>Ynp3H4rtzpXIh4TaVxkpEkS1bMCCu672aeCzUOzheNNfnpmLsCZz3+zQjMBbchPggCayC5ihpEdhRe3XvPXjPXXAgxDP4mic091QPmjHlmUcu8yqRKfxnPtD35nqaxDtCYw+jGIzj+ch094vA4RPCfY8JQnb1mpy1ZjjsMW8741CIh1epbsd/0bZt6tfINUQ37seg07yvLbCJZ/Zf+h8FlFryQk6lHTTeZl/GfQ9NlDBcShby3x8Hc1KwW++zFqEA7G783R9AYPYn3fWTOBhYk5gkgFc+HaPRLR/L0Bp7ZPbmOR/iZQ+HK4W672tTdN/R2GdN7/deV7QTp2DYK1Z8w==</ds:SignatureValue> 
       <ds:KeyInfo> 
        <wsse:SecurityTokenReference> 
         <wsse:Reference URI="#x509cert00" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509" /> 
        </wsse:SecurityTokenReference> 
       </ds:KeyInfo> 
      </ds:Signature> 
     </wsse:Security> 
    </SOAP-ENV:Header> 
    <SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TheBody"> 
     <getVersion xmlns="http://msgsec.wssecfvt.ws.ibm.com" /> 
    </SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 
+0

는 .NET Framework의 닷넷 표준 구현을하고 그것을 호출과 같은 일을 할 수 있나요? 그것은 또 다른 프로젝트 일 것이지만 일어 나고 시작하는 것이 더 쉬울 수도 있습니다. 나는 그것이 당신의 질문에 대답하지 않는다는 것을 압니다. 그러나 그것은 가능한 실행 가능한 일이 될 것입니다. – thinklarge

+0

나는 비슷한 요청으로 몇 주 전에 누군가를 도운다. 도움이 더 필요하면 알려주세요. 참조 : https://stackoverflow.com/questions/46722997/saml-assertion-in-a-xml-using-c-sharp/46724392#comment80642919_46724392 – jdweng

답변

1

내가 우리 자신의 비누 봉투를 압연하여이를 해결 : 우리는 인증서를 사용할 수와 같이 서명하고 싶습니다

<?xml version="1.0" encoding="UTF8"?> 
<SOAP-ENV:Envelope xmlns:SOAPENV="http://schemas.xmlsoap.org/soap/envelope/"> 
<SOAP-ENV:Header> 
<wsse:Security xmlns:ds="http://www.w3.org/2000/09/xmldsig#" 
      xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" 
      xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
      xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" 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#X509" 
      wsu:Id="x509cert00">BASE64_CERT</wsse:BinarySecurityToken> 
</wsse:Security> 
</SOAP-ENV:Header> 
<SOAP-ENV:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="TheBody"> 
<getVersion xmlns="http://msgsec.wssecfvt.ws.ibm.com"/> 
</SOAP-ENV:Body> 
</SOAP-ENV:Envelope> 

:

같은 요청을 감안할 때 그들에게 서명하고 HttpClient를 통해 파이핑합니다. .NET Core의 WCF는 제 3 자 서비스의 다양한 단점을 다루는 결과를 얻지 못했습니다.

여기 코드는, 당신의 요구 사항을 변경할 정도로 쉬워야한다이다 :

// ... 
private static HttpClient Client = new HttpClient(); // https://aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/ 
// ... 

Uri uri = new Uri("https://thirdparty.com/service.svc"); 
X509Certificate2 cert = // from some store etc 
var envelope = BuildEnvelope(cert); 

using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri)) 
{ 
    request.Content = new StringContent(envelope, Encoding.UTF8, "application/soap+xml"); 
    using (HttpResponseMessage response = Client.SendAsync(request).Result) 
    { 
     if (response.IsSuccessStatusCode) 
     { 
      response.Content.ReadAsStringAsync().ContinueWith(task => 
      { 
       string thirdparty_envelope = task.Result; 
       XElement thirdparty_root = XElement.Parse(thirdparty_envelope); 
       // etc 
      }, TaskContinuationOptions.ExecuteSynchronously); 
     } 
    } 
} 


private string BuildEnvelope(X509Certificate2 certificate) 
{ 
    string envelope = null; 
    // note - lots of bits here specific to my thirdparty 
    string cert_id = string.Format("uuid-{0}-1", Guid.NewGuid().ToString()); 
    using (var stream = new MemoryStream()) 
    { 
     Encoding utf8 = new UTF8Encoding(false); // omit BOM 
     using (var writer = new XmlTextWriter(stream, utf8)) 
     { 
      // timestamp 
      DateTime dt = DateTime.UtcNow; 
      string now = dt.ToString("o").Substring(0, 23) + "Z"; 
      string plus5 = dt.AddMinutes(5).ToString("o").Substring(0, 23) + "Z"; 

      // soap envelope 
      // <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:u="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> 
      writer.WriteStartDocument(); 
      writer.WriteStartElement("s", "Envelope", "http://www.w3.org/2003/05/soap-envelope"); 
      writer.WriteAttributeString("xmlns", "a", null, "http://www.w3.org/2005/08/addressing"); 
      writer.WriteAttributeString("xmlns", "u", null, "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"); 

      writer.WriteStartElement("s", "Header", null); 

      ///////////////// 
      // saml guts // 
      ///////////////// 

      //<a:Action s:mustUnderstand="1">http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue</a:Action> 
      writer.WriteStartElement("a", "Action", null); 
      writer.WriteAttributeString("s", "mustUnderstand", null, "1"); 
      writer.WriteString("http://docs.oasis-open.org/ws-sx/ws-trust/200512/RST/Issue"); 
      writer.WriteEndElement(); //Action 

      //<a:MessageID>urn:uuid:0cc426dd-35bf-4c8b-a737-7e2ae94bd44d</a:MessageID> 
      string msg_id = string.Format("urn:uuid:{0}", Guid.NewGuid().ToString()); 
      writer.WriteStartElement("a", "MessageID", null); 
      writer.WriteString(msg_id); 
      writer.WriteEndElement(); //MessageID 

      //<a:ReplyTo><a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address></a:ReplyTo> 
      writer.WriteStartElement("a", "ReplyTo", null); 
      writer.WriteStartElement("a", "Address", null); 
      writer.WriteString("http://www.w3.org/2005/08/addressing/anonymous"); 
      writer.WriteEndElement(); //Address 
      writer.WriteEndElement(); //ReplyTo 

      writer.WriteStartElement("a", "To", "http://www.w3.org/2005/08/addressing"); 
      writer.WriteAttributeString("s", "mustUnderstand", null, "1"); 
      writer.WriteAttributeString("u", "Id", null, "_1"); 
      writer.WriteString("https://thirdparty.com/service.svc"); 
      writer.WriteEndElement(); //To 

      //<o:Security xmlns:o="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1"> 
      writer.WriteStartElement("o", "Security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
      writer.WriteAttributeString("s", "mustUnderstand", null, "1"); 

      //<u:Timestamp u:Id="_0"> 
      writer.WriteStartElement("u", "Timestamp", null); 
      writer.WriteAttributeString("u", "Id", null, "_0"); 

      //<u:Created>2018-02-08T15:03:13.115Z</u:Created> 
      writer.WriteElementString("u", "Created", null, now); 

      //<u:Expires>2018-02-08T15:08:13.115Z</u:Expires> 
      writer.WriteElementString("u", "Expires", null, plus5); 

      writer.WriteEndElement(); //Timestamp 

      writer.WriteStartElement("o", "BinarySecurityToken", null); 
      writer.WriteAttributeString("u", "Id", null, cert_id); 
      writer.WriteAttributeString("ValueType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"); 
      writer.WriteAttributeString("EncodingType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"); 
      byte[] rawData = certificate.GetRawCertData(); 
      writer.WriteBase64(rawData, 0, rawData.Length); 
      writer.WriteEndElement(); //BinarySecurityToken 

      writer.WriteEndElement(); //Security 
      writer.WriteEndElement(); //Header 

      //<s:Body xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
      writer.WriteStartElement("s", "Body", "http://www.w3.org/2003/05/soap-envelope"); 
      writer.WriteAttributeString("xmlns", "xsd", null, "http://www.w3.org/2001/XMLSchema"); 
      writer.WriteAttributeString("xmlns", "xsi", null, "http://www.w3.org/2001/XMLSchema-instance"); 

      // your 3rd-party soap payload goes here 
      writer.WriteStartElement("???", "http://docs.oasis-open.org/ws-sx/ws-trust/200512"); 
      // ...     
      writer.WriteEndElement(); // 
      writer.WriteEndElement(); // Body 


      writer.WriteEndElement(); //Envelope 
     } 

     // signing pass 
     var signable = Encoding.UTF8.GetString(stream.ToArray()); 
          XmlDocument doc = new XmlDocument(); 
     doc.LoadXml(signable); 

     // see https://stackoverflow.com/a/6467877 
     var signedXml = new SignedXmlWithId(doc); 

     var key = certificate.GetRSAPrivateKey(); 
     signedXml.SigningKey = key; 
     // these values may not be supported by your 3rd party - they may use e.g. SHA256 miniumum 
     signedXml.SignedInfo.CanonicalizationMethod = SignedXml.XmlDsigExcC14NTransformUrl; 
     signedXml.SignedInfo.SignatureMethod = SignedXml.XmlDsigRSASHA1Url; 

     // 
     KeyInfo keyInfo = new KeyInfo(); 
     KeyInfoX509Data x509data = new KeyInfoX509Data(certificate); 
     keyInfo.AddClause(x509data); 
     signedXml.KeyInfo = keyInfo; 

     // 3rd party wants us to only sign the timestamp fragment- ymmv 
     Reference reference0 = new Reference(); 
     reference0.Uri = "#_0"; 
     var t0 = new XmlDsigExcC14NTransform(); 
     reference0.AddTransform(t0); 
     reference0.DigestMethod = SignedXml.XmlDsigSHA1Url; 
     signedXml.AddReference(reference0); 
     // etc 

     // get the sig fragment 
     signedXml.ComputeSignature(); 
     XmlElement xmlDigitalSignature = signedXml.GetXml(); 

     // modify the fragment so it points at BinarySecurityToken instead 
     XmlNode info = null; 
     for (int i = 0; i < xmlDigitalSignature.ChildNodes.Count; i++) 
     { 
      var node = xmlDigitalSignature.ChildNodes[i]; 
      if (node.Name == "KeyInfo") 
      { 
       info = node; 
       break; 
      } 
     } 
     info.RemoveAll(); 

     // 
     XmlElement securityTokenReference = doc.CreateElement("o", "SecurityTokenReference", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
     XmlElement reference = doc.CreateElement("o", "Reference", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
     reference.SetAttribute("ValueType", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3"); 
     // cert id     
     reference.SetAttribute("URI", "#" + cert_id); 
     securityTokenReference.AppendChild(reference); 
     info.AppendChild(securityTokenReference); 

     var nsmgr = new XmlNamespaceManager(doc.NameTable); 
     nsmgr.AddNamespace("o", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"); 
     nsmgr.AddNamespace("s", "http://www.w3.org/2003/05/soap-envelope"); 
     var security_node = doc.SelectSingleNode("/s:Envelope/s:Header/o:Security", nsmgr); 
     security_node.AppendChild(xmlDigitalSignature); 

     envelope = doc.OuterXml; 
    } 

    return envelope; 
}