I have successfully created a WS client that works correctly when NOT using authentication.
However, the server (WebSphere) now requires adding a ws-security username token, and I'm having a hard time doing this. The resulting SOAP message is supposed to look something like this:
<soapenv:Envelope
xmlns:ns="http://foo.bar/1.0"
xmlns:ns1="http://www.witsml.org/schemas/140"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header>
<wsse:Security soapenv: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-2" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
<wsse:Username>foo</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">bar</wsse:Password>
<wsse:Nonce EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary">foooooobar==</wsse:Nonce>
<wsu:Created>2010-01-25T13:09:24.860Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<ns:fooBar>...</ns:fooBar>
</soapenv:Body>
I've downloaded and installed Microsoft's WSE 3.0 SDK and added a reference to the DLL in my Visual Studio 2005 project.
I now have access to the Microsoft.Web.Services3.* namespaces, but I'm currently stumped on how to proceed.
The client code has been generated automatically by a web reference, so I only do a minor amount of work to send the message to the server unauthenticated:
WS.FooResultHttpService ws = new WS.FooResultHttpService();
ws.Url = "http://foo.bar.baz";
ws.SendSomething(message);
I've just begun to investigate using Microsoft.Web.Services3.Security.Tokens.UsernameTokenManager
, but so far I haven't been able to get anything up and running.
Any hints would be greatly appreciated, as I can't seem to find any good recipes on the net.
Thanks!
Make sure your proxy class inherits from Microsoft.Web.Services3.WebServicesClientProtocol
.
You can do this either by changing the proxy class itself, or by generating it via the command line using wsewsdl3.exe with the /type:webClient
switch.
You can then pass the credentials like this:
using Microsoft.Web.Services3;
using Microsoft.Web.Services3.Security.Tokens;
using Microsoft.Web.Services3.Security;
.
.
.
WS.FooResultHttpService ws = new WS.FooResultHttpService();
ws.RequestSoapContext.Security.Tokens.Add(new UsernameToken("blah", "blah", PasswordOption.SendPlainText));
This is what I've done in the past to get WSE3.0 going in Studio 2008. Hope that helps.
Got it working, unfortunately before reading wsanville's great answer.
To help others, I'm posting all the steps I needed to do to get it working with Visual Studio 2005:
YourWsNameHttpServiceWse
. This is essentially the same as running wsewsdl3.exe
SetClientCredential
.I ended up doing almost everything in code, instead of relying on the config-files that are built with my C# DLL. The code ended up looking like this:
FooBarHttpServiceWse wse = new FooBarHttpServiceWse();
wse.SetClientCredential(new UsernameToken(
"username",
"password",
PasswordOption.SendPlainText));
wse.SetPolicy(new FooBarPolicy());
wse.CallSomeServerFunction(yourRequest)
I created my own policy, which looked like this:
using Microsoft.Web.Services3.Design;
// ...
public class FooBarPolicy : Policy
{
public FooBarPolicy()
{
this.Assertions.Add(new UsernameOverTransportAssertion());
}
}
Finally, the WebSphere server responded that A required header representing a Message Addressing Property is not present, and inspecting the outgoing message (using the nice tool Fiddler) I saw the SOAP fault from the server indicated that the Action header was missing.
I tried in vain to set the wsa:Action
element myself:
using Microsoft.Web.Services3.Addressing;
// ...
wse.RequestSoapContext.Addressing.Action = new Action("CallSomeServerFunction");
The problem was that even if I set an action, when it was sent over the wire, it was empty. Turned out I had to open the WSE proxy class and edit an attribute there:
[System.Web.Services.Protocols.SoapDocumentMethodAttribute(
"---Edit this to set wsa:Action---",
Use=System.Web.Services.Description.SoapBindingUse.Literal,
ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Bare)]
// ...
public SomeServerFunction(...)
After that, it all worked out nicely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With