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 はプレーン テキストですが、暗号化する必要があります。
最初にメソッド EncryptAndSingXml をクラス SoapMsg の void として使用し、正しく動作するためです!!! このようなもの :
public class SoapMsg : SoapExtension
{
//...
public void EncryptAndSingXml()
{...}
//...
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
//...
case SoapMessageStage.AfterSerialize:
EncryptAndSingXml();
break;
//...
}
// ...
}
しかし、クラス CryptUtility とメソッド EncryptAndSingXml() を仮想として作成すると、機能しません。:( 誰かが私を助けることができますか?