简体   繁体   中英

Remove timestamp element from ws-security headers created by WCF

I am consuming an old Java web service from WCF that requires the request in the form:

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
    <s:Header>
        <wsse:Security mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss- wssecurity-secext-1.0.xsd">
            <wsse:UsernameToken wsu:Id="xxx" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-ssecurity-utility-1.0.xsd">
                <wsse:Username>username</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </s:Header>
    <s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        ...
    </s:Body>
</s:Envelope>

Using the following config hack "works" but I don't want the username and password exposed in config:

<binding name="bindingName">
      <security mode="Transport">
        <transport clientCredentialType="Certificate" />
      </security>
</binding>
...
<endpoint address="https://endpoint address"
      binding="basicHttpBinding" bindingConfiguration="bindingName"
      contract="contract"
      name="bindingName">

    <headers>
        <wsse:Security mustUnderstand="1" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss- wssecurity-secext-1.0.xsd">
            <wsse:UsernameToken wsu:Id="UsernameToken-8293453" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-ssecurity-utility-1.0.xsd">
                <wsse:Username>username</wsse:Username>
                <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">password</wsse:Password>
            </wsse:UsernameToken>
        </wsse:Security>
    </headers>
</endpoint>

What I want to use is something along the lines of:

<binding name="bindingName">
    <security mode="TransportWithMessageCredential">
        <transport clientCredentialType="Certificate" />
        <message clientCredentialType="UserName" />
    </security>
</binding>

But this generates the timestamp element in the security element, which the java webservice borks on.

What I need to do is remove the timestamp from the XML it generates or have some sort of custom binding to do it for me.

I tried creating custom credentials, but this only changed the usernameToken element.

I have already looked at many, many SO questions (many from 2007 and earlier) including the following with no joy:

What is the best, simplest and most elegant way to remove the timestamp element.

Thanks in advance

Found the answer on Kristian Kristensen's blog post about his woes in integrating to a Java AXIS 1.X and WSS4J web service. . So much simpler and easier than the hacks I was trying previously.

You can solve this with a simple custom binding in App.config as so:

BUGFIX - there is a bug in previous version - forgot to add certificate in httpTransport

<system.serviceModel>
    <bindings>
        <customBinding>
            <binding name="CustomBindingName">
                <security authenticationMode="UserNameOverTransport" includeTimestamp="false">
                    <secureConversationBootstrap />
                </security>
                <textMessageEncoding messageVersion="Soap11" />
                <httpsTransport useDefaultWebProxy="false" requireClientCertificate="true" />
            </binding>
        </customBinding>
    </bindings>

    <client>
        <endpoint address="<endpoint address>" 
            binding="customBinding"
            bindingConfiguration="CustomBindingName"
            contract="<contract goes here>"
            name="EndpointName" />

    </client>
</system.serviceModel>

This gives the correct SOAP ws-security header without the timestamp that confused the java server just by calling this code

var client = new [clientType]();

client.ClientCredentials.ClientCertificate.Certificate = [certificate];

client.ClientCredentials.UserName.UserName = [UserName];
client.ClientCredentials.UserName.Password = [Password];

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;

// TODO wrap in try catch
client.Open();

var result = client.[action](new [RequestType] { ... });

Further Reading:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM