我尝试在ASP.NET Web服务中唱歌和加密SOAP消息。
//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;
}
}
我在Soap扩展类中使用了CryptUtility对象:
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.");
}
}
// ...
}
问题是,当我在AfterDeserialize中记录SOAP消息时,XML是纯文本,但它应该加密 有人可以帮助我,哪里可能有问题,或者我可以做些什么?
因为首先我在SoapMsg类中使用方法EncryptAndSingXml作为void,它工作正常!!! 像这样:
public class SoapMsg : SoapExtension
{
//...
public void EncryptAndSingXml()
{...}
//...
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
//...
case SoapMessageStage.AfterSerialize:
EncryptAndSingXml();
break;
//...
}
// ...
}
但是当我将类CryptUtility和方法EncryptAndSingXml()作为虚拟时,它不起作用。 :( 有人可以帮帮我吗?
答案 0 :(得分:1)
看起来你根本不在修改message
!
并且,请显示您创建CryptUtility
的实例的位置。
此外,您的代码非常糟糕。试试这个:
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;
}
}
}
和
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.");
}
}
// ...
}