问题
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!
回答1:
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.
回答2:
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:
- Install WSE 3.0, choose custom and select everything
- Read Implementing direct authentication with username token in WSE 3.0 for hints
- Relaunch Visual Studio 2005, now right-click on your project in the solution explorer, and you should have a WSE Settings 3.0 menu item and use that if you want to.
- Update your web references, this should create a new HTTP web service proxy class, with a different name, e.g.
YourWsNameHttpServiceWse
. This is essentially the same as running wsewsdl3.exe - Use this new class, and you should have access to WSE methods and properties, such as
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.
来源:https://stackoverflow.com/questions/2139190/adding-soapheader-username-and-password-with-wse-3-0