Showing posts with label Web Services. Show all posts
Showing posts with label Web Services. Show all posts
Monday, November 25, 2013
Configuration of Class Library
I have developed a ws client in a class library and the code of the ws client is generated by adding a web references. When I want to move the ws client from uat environment to production environment, the client does not work at all. The problem is raised since I only update the configuration of app.config inside the class library. As the ws client is a class library, the configuration in app.config will be ignored. Afterwards, I update the Reference.cs which is generated by vs.
.Net: This application needs to use a cryptographic key
My application is required to integrated with a HTTPS web services. A popup windows is shown when I execute the console application under debug mode. It requests some permission for key access. After I grant the access, the application works fine.
Then, I publish the application to IIS and windows security popup is shown when I browse the site. Actually, the site doesn't work.
The absence of windows security popup gives me some idea on the permission on existing private key.
There are two ways to solve above issue.
1. Give permission to this folder C:\ProgramData\Microsoft\Crypto\RSA\MachineKeys directly
2. Go to cmd-> type "mmc"-> add snapin certificate->click folder personal->right click->All Tasks->import your private key->right click your private key->All Tasks->Manage Private Key...->grant the permission.
Friday, September 27, 2013
Soap WS-Security Header : One of "SOAP Header" elements required
I run a C# web service client to connect to a Java web service. Then, it throws a exception: [com.ibm.wsspi.wssecurity.SoapSecurityException:WSEC5048EL One of "SOAP Header" elements required]. As no header is defined in the wsdl, I have no idea about the exception and don't know what should be added to the header. Further, the generated web service client does not have a header property. That means, I cannot add the header to the client directly.
After searching, I found out that WS-Security is a standard.
Then, I try to find out where I can insert the header to the requested XML. Below it's a one of the solutions that I found out on ASP.NET forum.
WSHeader .cs
public class WSHeader : SoapExtension
{
public bool outgoing = true;
public bool incoming = false;
private Stream outputStream;
public Stream oldStream;
public Stream newStream;
// The ChainStream, GetInitializers, Initialize, and ProcessMessage are required
// for a Soap override. ChainStream and ProcessMessage are what we need.
/// <summary>
/// Override. Save old stream, create new one.
/// </summary>
/// <param name="stream"></param>
/// <returns></returns>
public override Stream ChainStream(Stream stream)
{
// save a copy of the stream, create a new one for manipulating.
this.outputStream = stream;
oldStream = stream;
newStream = new MemoryStream();
return newStream;
}
#region "overrides of no interest"
public override object GetInitializer(LogicalMethodInfo methodInfo, SoapExtensionAttribute attribute)
{
throw new Exception("The method or operation is not implemented.");
}
public override object GetInitializer(Type serviceType)
{
return null;
}
public override void Initialize(object initializer)
{
return;
}
#endregion
/// <summary>
/// Return a string version of the XML
/// </summary>
/// <returns></returns>
public string getXMLFromCache()
{
newStream.Position = 0; // start at the beginning!
string strSOAPresponse = ExtractFromStream(newStream);
return strSOAPresponse;
}
/// <summary>
/// Transfer the text from the target stream from the
/// current position.
/// </summary>
/// <param name="target"></param>
/// <returns></returns>
private String ExtractFromStream(Stream target)
{
if (target != null)
return (new StreamReader(target)).ReadToEnd();
return "";
}
/// <summary>
/// Override. Process .AfterSerialize and .BeforeDeserialize
/// to insert a non-standard SOAP header with username and
/// password (currently hard-coded).
/// </summary>
/// <param name="message"></param>
public override void ProcessMessage(SoapMessage message)
{
StreamReader readStr;
StreamWriter writeStr;
string soapMsg1;
XmlDocument xDoc = new XmlDocument();
// a SOAP message has 4 stages. We're interested in .AfterSerialize
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
{
// Get the SOAP body as a string, so we can manipulate...
String soapBodyString = getXMLFromCache();
// Strip off the old header stuff before the message body
// I'm not completely sure, but the soap:encodingStyle might be
// unique to the WebSphere environment. Dunno.
String BodString = "<soap:Body>";
int pos1 = soapBodyString.IndexOf(BodString) + BodString.Length;
int pos2 = soapBodyString.Length - pos1;
soapBodyString = soapBodyString.Substring(pos1, pos2);
soapBodyString = "<soap:Body>" + soapBodyString;
// Create the SOAP Message
// It's comprised of a <soap:Element> that's enclosed in <soap:Body>.
// Pack the XML document inside the <soap:Body> element
//String xmlVersionString = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
String soapEnvelopeBeginString = "<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:tns=\"http://tempuri.org/\" xmlns:types=\"http://tempuri.org/encodedTypes\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">";
String soapEnvHeaderString = "<soap:Header><Security><UsernameToken><Username>";
String soapEnvHeaderString2 = "</Username><Password>";
String soapEnvHeaderString3 = "</Password></UsernameToken></Security></soap:Header>";
Stream appOutputStream = new MemoryStream();
StreamWriter soapMessageWriter = new StreamWriter(appOutputStream);
//soapMessageWriter.Write(xmlVersionString);
soapMessageWriter.Write(soapEnvelopeBeginString);
//// The heavy-handed part - forcing the right headers AND the uname/pw :)
soapMessageWriter.Write(soapEnvHeaderString);
soapMessageWriter.Write(ConfigurationManager.AppSettings["WSUserName"]);
soapMessageWriter.Write(soapEnvHeaderString2);
soapMessageWriter.Write(ConfigurationManager.AppSettings["WSPassword"]);
soapMessageWriter.Write(soapEnvHeaderString3);
// End clubbing of baby seals
// Add the soapBodyString back in - it's got all the closing XML we need.
//soapBodyString = dammit;
soapMessageWriter.Write(soapBodyString);
// write it all out.
soapMessageWriter.Flush();
appOutputStream.Flush();
appOutputStream.Position = 0;
StreamReader reader = new StreamReader(appOutputStream);
StreamWriter writer = new StreamWriter(this.outputStream);
writer.Write(reader.ReadToEnd());
writer.Flush();
appOutputStream.Close();
this.outgoing = false;
this.incoming = true;
break;
}
case SoapMessageStage.BeforeDeserialize:
{
//Make the output available for the client to parse...
readStr = new StreamReader(oldStream);
writeStr = new StreamWriter(newStream);
soapMsg1 = readStr.ReadToEnd();
xDoc.LoadXml(soapMsg1);
soapMsg1 = xDoc.InnerXml;
writeStr.Write(soapMsg1);
writeStr.Flush();
newStream.Position = 0;
break;
}
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new Exception("invalid stage!");
}
}
}
Add following to web.config
<system.web>
<webServices>
<soapExtensionTypes>
<add type="TDCWS.WSHeader,TDCWS" priority="1" group="Low"/>
</soapExtensionTypes>
</webServices>
</system.web>
Hope that can help!
References:
Subscribe to:
Posts (Atom)