1

I need some help to consume a web service using SOAP. My application use .NET 4.0.

The SOAP request have to follow the following requirments :

I have to use two differents certificats for encryption and signing.

The WCF configuration should be configurable (the signature can be desactivated). So the bindings have to be created in c# code and not in app.config.

Sample of request expected by the server :

<s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope">
   <s:Header>
      <wsse:Security 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">
         <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-C6D119F21B41F79DBF154885449980234">
            <ds:SignedInfo>
               <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                  <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="s" />
               </ds:CanonicalizationMethod>
               <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
               <ds:Reference URI="#id-5">
                  <ds:Transforms>
                     <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
                        <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="" />
                     </ds:Transform>
                  </ds:Transforms>
                  <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
                  <ds:DigestValue>...</ds:DigestValue>
               </ds:Reference>
            </ds:SignedInfo>
            <ds:SignatureValue>...</ds:SignatureValue>
            <ds:KeyInfo Id="KI-C6D119F21B41F79DBF154885449979232">
               <wsse:SecurityTokenReference wsu:Id="STR-C6D119F21B41F79DBF154885449979233">
                  <ds:X509Data>
                     <ds:X509IssuerSerial>
                        <ds:X509IssuerName>CN=..,O=...,C=..</ds:X509IssuerName>
                        <ds:X509SerialNumber>...</ds:X509SerialNumber>
                     </ds:X509IssuerSerial>
                  </ds:X509Data>
               </wsse:SecurityTokenReference>
            </ds:KeyInfo>
         </ds:Signature>
      </wsse:Security>
   </s:Header>
   <s:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-5">
      ...
   </s:Body>
</s:Envelope>

My first attempt was to generate and send the request using WCF but I didn't find out how to generate something following the requirement. Then I try to generate the signature manually and use an IClientMessageFormatter and a IEndpointBehavior to create the header manualy. This solution didn't work because WCF applies treatments (switching xml attributes and namespaces...) that invalidates the signature. My last attempt was to completly remove WCF and send the request manualy but HttpClient is not available in .NET 4.0 and I didn't find out how to send TLS request without it.

Can anyone tell me how to configure WCF to generate the right SOAP request ? If the request can't be created with WCF, how can I send TLS request (and handle a responce) with .NET 4.0?

Thanks.

  • See my solution at follwing posting : https://stackoverflow.com/questions/46722997/saml-assertion-in-a-xml-using-c-sharp/46724392 – jdweng Feb 08 '19 at 11:36
  • Your post show how to create the content of the signed soap request. I already have a method to generate the content manualy. I need help to send the data with SSL v3/TLS v1.0 (.NET 4.0) or to generate the request with WCF (SSL is easy to configure with WCF) – Marc Unterseh Feb 08 '19 at 12:44
  • Use bindings in code to change the request accordingly, use service interfaces if possible to create the classes, then you can use a ClientFactory to interchange the various inspectors that will change the message – mahlatse Feb 08 '19 at 12:57

1 Answers1

0

As far as I know, header could be configured in web.config or app.config.

<endpoint address="http://ws-wuxipc-5077:4000/calculator" binding="basicHttpBinding"
  contract="ServiceInterface.ICalculatorService" name="cal">
  <headers>
    <Security xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
      <wsse:UsernameToken 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">
        <wsse:Username>
        </wsse:Username>
        <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest">monMonDePasse</wsse:Password>
        <wsse:Nonce>sdsdsdlojhfdsdM5Nw==</wsse:Nonce>
        <wsu:Created>2019-01-21T6:17:34Z</wsu:Created>
      </wsse:UsernameToken>
    </Security>
  </headers>
</endpoint>

You could also add header in your code through xml.

 using (ChannelFactory<ICalculatorService> ChannelFactory = new ChannelFactory<ICalculatorService>("cal"))
        {
            // ChannelFactory.Endpoint.EndpointBehaviors.Add(new MyEndpointBehavior());
            ICalculatorService employeeService = ChannelFactory.CreateChannel();
            using (OperationContextScope scope = new OperationContextScope((IContextChannel)employeeService))
            {

                System.Xml.XmlDocument document = new XmlDocument();


                XmlElement element = document.CreateElement("wsse", "UsernameToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");


                XmlElement newChild = null;

                newChild = document.CreateElement("wsse", "Username", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                newChild.InnerText = "finance";
                element.AppendChild(newChild);

                newChild = document.CreateElement("wsse", "password", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
                newChild.SetAttribute("Type", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest");
                newChild.InnerText = "387";
                element.AppendChild(newChild);

                MessageHeader messageHeader = MessageHeader.CreateHeader("security", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", element, false);


                OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader);
                employeeService.Add(5, 6);
            }

            // List<Employee> list=  employeeService.GetList();
            Console.Read();
        }
Ackelry Xu
  • 756
  • 3
  • 6