ASMX web service with Soap extension - problem with Encryption method
I try sing and encrypt SOAP message in ASP.NET Web Service.
//I have Crypt class, which input parameters is Stream:
public class CryptUtility
{
public virtual Stream EncryptAndSingXml (Stream inputStream)
{
XmlTextReader reader = new XmlTextReader(inputStream);
XmlDocument doc = new XmlDocument();
doc.Load(reader);
// in this place I encrypt and sign SOAP message
foreach (string xPathQuery in soapElement)
{
XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
{
// method EncryptString crypt only string from XmlNode
nodeToEncrypt.InnerXml = EncryptString();
}
}
// !!!
// I THINK HERE IS A PROBLEM
//
//it return plain stream, no encrypt stream
MemoryStream retStream = new MemoryStream();
XmlTextWriter writer = new XmlTextWriter(retStream, Encoding.UTF8);
doc.Save(retStream);
return retStream;
}
}
I used CryptUtility object in Soap extension class:
public class SoapMsg : SoapExtension
{
private CryptUtility cryptUtil; //this object crypt and sing SOAP message
// ...
//this method copy stream
private void CopyStream(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.Write(reader.ReadToEnd());
writer.Flush();
}
//this method sing and encrypt SOAP message, I call this method in stage AfterSerialize
private void CryptMessage()
{
newStream.Position = 0;
Stream retStream = cryptUtil.EncryptAndSingXml(newStream);
retStream.Position = 0;
CopyStream(retStream, oldStream);
}
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
{
// call the crypt and sing method
CryptMessage();
//save the SOAP message, the message is not encrypt
Log(message, "AfterSerialize");
}
break;
case SoapMessageStage.BeforeDeserialize:
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new ArgumentException("error.");
}
}
// ...
}
Problem is, when I log SOAP message in AfterDeserialize the XML is plain text, but it should be encrypt Can somebody help me, where can be problem , or what can I do bad?
Because first I use method EncryptAndSingXml as void in class SoapMsg, and it work correct!!! Something like this :
public class SoapMsg : SoapExtension
{
//...
public void EncryptAndSingXml()
{...}
//...
public override void Proc开发者_C百科essMessage(SoapMessage message)
{
switch (message.Stage)
{
//...
case SoapMessageStage.AfterSerialize:
EncryptAndSingXml();
break;
//...
}
// ...
}
But when I makec class CryptUtility and method EncryptAndSingXml() as virtual it doesn't work. :( Can somebody help me ?
It doesn't look like you are modifying message
at all!
And, please show where you create an instance of CryptUtility
.
Also, your code is pretty bad. Try this:
public class CryptUtility
{
public virtual Stream EncryptAndSingXml(Stream inputStream, IEnumerable<string> soapElement)
{
XmlDocument doc = new XmlDocument();
using (XmlReader reader = XmlReader.Create(inputStream))
{
doc.Load(reader);
}
// in this place I encrypt and sign SOAP message
XmlNamespaceManager nsMan = new XmlNamespaceManager(doc.NameTable);
foreach (string xPathQuery in soapElement)
{
XmlNodeList nodesToEncrypt = doc.SelectNodes(xPathQuery, nsMan);
foreach (XmlNode nodeToEncrypt in nodesToEncrypt)
{
// method EncryptString crypt only string from XmlNode
nodeToEncrypt.InnerXml = EncryptString(nodeToEncrypt.InnerXml);
}
}
// !!!
// I THINK HERE IS A PROBLEM
//
//it return plain stream, no encrypt stream
using (MemoryStream retStream = new MemoryStream())
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.Encoding = Encoding.UTF8;
using (XmlWriter writer = XmlWriter.Create(retStream, settings))
{
doc.WriteTo(writer);
}
return retStream;
}
}
}
and
public class SoapMsg : SoapExtension
{
private CryptUtility cryptUtil; //this object crypt and sing SOAP message
// ...
//this method copy stream
private void CopyStream(Stream from, Stream to)
{
using (TextReader reader = new StreamReader(from))
{
using (TextWriter writer = new StreamWriter(to))
{
writer.Write(reader.ReadToEnd());
writer.Flush();
}
}
}
//this method sing and encrypt SOAP message, I call this method in stage AfterSerialize
private void CryptMessage()
{
newStream.Position = 0;
using (Stream retStream = cryptUtil.EncryptAndSingXml(newStream))
{
retStream.Position = 0;
CopyStream(retStream, oldStream);
}
}
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
{
// call the crypt and sing method
CryptMessage();
//save the SOAP message, the message is not encrypt
Log(message, "AfterSerialize");
}
break;
case SoapMessageStage.BeforeDeserialize:
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new ArgumentException("error.");
}
}
// ...
}
精彩评论