A Coder's Blog
It could happen that you have to interface your WCF client to a web service that uses WS-Security/WSE protocol. Web Services Security (WS-Security, WSS) is an extension to SOAP to apply security to Web services.
Unfortunately WS-Security/WSE protocol is not natively supported in .NET WCF 4.
WSS incorporates security features in the header of a SOAP message. Inside the header of a SOAP message, WSS has a security element (one or more than one) used to verify the end-user identity. Example:
<soap:Envelope>
<soap:Header>
<wsse:Security>
<wsse:UsernameToken>
<wsse:Username>user</wsse:Username>
<wsse:Password>password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
In order to allow your WCF client application to communicate with a WSS service a possible solution could be the following:
Capture the raw soap message before it gets submitted: capture raw soap messages
Implement BeforeSendRequest method in CapturingMessageInspector class (the following code is going to modify the soap message injecting the wss security header):
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel)
{
var soapModified = InjectWsseHeader(request.ToString());
var ms = new MemoryStream();
var writer = new StreamWriter(ms);
writer.Write(soapModified);
writer.Flush();
ms.Position = 0;
var reader = XmlReader.Create(ms);
request = System.ServiceModel.Channels.Message.CreateMessage(reader, int.MaxValue, request.Version);
this.SoapMessages.Request = soapModified;
return null;
}
private string InjectWsseHeader(string request)
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(request);
XmlNode root = xmlDoc.DocumentElement;
var sseNamespace = "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
XmlElement sseSecurityHeader = xmlDoc.CreateElement("wsse", "Security", sseNamespace);
XmlElement usernameToken = xmlDoc.CreateElement("wsse", "UsernameToken", sseNamespace);
XmlElement username = xmlDoc.CreateElement("wsse", "Username", sseNamespace);
username.InnerText = "your username ..";
XmlElement password = xmlDoc.CreateElement("wsse", "Password", sseNamespace);
password.InnerText = "your password ..";
usernameToken.AppendChild(username);
usernameToken.AppendChild(password);
sseSecurityHeader.AppendChild(usernameToken);
root.FirstChild.AppendChild(sseSecurityHeader);
using (var stringWriter = new StringWriter())
using (var xmlTextWriter = XmlWriter.Create(stringWriter))
{
xmlDoc.WriteTo(xmlTextWriter);
xmlTextWriter.Flush();
return stringWriter.GetStringBuilder().ToString();
}
}