I'm have near to none experience with SOAP protocol. The service I need to connect to required header. I think this is somewhat standard in Java but in C# one must create this header by hand.
Does anyone here been able to connect to similar service: have created the header or maybe even know about some standard library which would simplify creation of header? Can you share some code or references?
I also found a clue that maybe header will be generated if using WS2005, because there is WS3 addin for it. Can anybody comment this? After quick look at this addin I found simmilar fields as in Security header, but still wasn't able to create the header.
ClientCridentials. UserName. Password = "testPass"; In this way you can pass username, password in the header to a SOAP WCF Service.
The basic premise of WSSE is that a request header is checked for encrypted credentials, verified using a timestamp and nonce, and authenticated for the requested user using a password digest. It is implemented by the OroWsseAuthenticationBundle that covers most cases from the WSSE specification (PDF).
Nonce is a randomly-generated, cryptographic token that is used to prevent replay attacks. Although nonce can be inserted anywhere in the SOAP message, it is typically inserted in the <UsernameToken> element.
We were able to solve it with the following code:
public class SecurityHeader : System.ServiceModel.Channels.MessageHeader {
public string userName;
public string password;
protected override void OnWriteStartHeader (System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
{
writer.WriteStartElement("wsse", Name, Namespace);
writer.WriteXmlnsAttribute("wsse", Namespace);
}
protected override void OnWriteHeaderContents (System.Xml.XmlDictionaryWriter writer, System.ServiceModel.Channels.MessageVersion messageVersion)
{
writer.WriteStartElement("wsse", "UsernameToken", Namespace);
writer.WriteStartElement("wsse", "Username", Namespace);
writer.WriteValue(userName);
writer.WriteEndElement();
writer.WriteStartElement("wsse", "Password", Namespace);
writer.WriteValue(password);
writer.WriteEndElement();
writer.WriteEndElement();
}
public override string Name
{
get { return "Security"; }
}
public override string Namespace
{
get { return "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"; }
}
}
This wrote the header that was required by the DataPower box.
How to use the class SecurityHeader
public static void Main(string[] args)
{
var webService = new ServiceReference1.MyWebService();
....
webService.Open();
using (OperationContextScope scope = new OperationContextScope((IContextChannel)webService.InnerChannel))
{
var myObjRequest = GetMyObjRequest();
MessageHeaders messageHeadersElement = OperationContext.Current.OutgoingMessageHeaders;
messageHeadersElement.Add(SecurityHeader("UserName", "Password"))
var res = webService.MyServe(myObjRequest);
Console.WriteLine(res.ToString());
}
}
Funny you should mention that - I've been doing exactly that recently.
I've managed to do it using a SoapExtension
which uses ChainStream
to keep a copy of the original stream, just copies the stream during BeforeDeserialize
and adds the header during AfterSerialize
.
Adding the header is a case of reading the contents of the "new" stream (returned from ChainStream
) into an XML document (XDocument
in my case), adding the header, and then writing it to the original stream passed into ChainStream
.
Unfortunately this is pretty dirty, and you can't (as far as I'm aware) use a new instance with appropriate authentication information when you need to.
I've got most of the way using a SoapHeader
instead, adding an appropriate attribute to each method of the web service and also an appropriate field/property with an instance of the required header - but the SOAP serialization is currently giving me headaches in terms of specifying the right element names (with namespaces). It's something I've been planning to ask others about when I get the time.
Sorry not to be able to give you a full answer - and also apologies for the lack of code, it belonging to the company rather than me - but hopefully it'll at least give you a starting point.
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