我在Soap扩展中调用方法来解密和验证唱Soap消息。 我有这个课程:
我有一个类,它解密并验证了标志Soap消息,它在Soap扩展类中返回流:
方法DecryptAndVerifySingXml和GetGuid使用来自类soap扩展的流。
public class CryptUtility
{
public virtual Stream DecryptAndVerifySingXml(Stream inputStream)
{
XmlDocument doc = new XmlDocument();
using (XmlTextReader reader = new XmlTextReader(inputStream))
{
doc.Load(reader);
}
using (MemoryStream retStream = new MemoryStream())
{
retStream.Position = 0;
doc.Save(retStream);
}
//.....crypt and verify sing
if (signedXml.CheckSignature(Key) == false)
{
throw new SecurityException("error");
}
else
{
using (MemoryStream retStream = new MemoryStream())
{
doc.Save(retStream);
return retStream;
}
}
}
//get value from Soap header
public string GetGuid(MemoryStream inputStream)
{
inputStream.Position = 0;
string soapBodyString = Encoding.UTF8.GetString(inputStream.ToArray());
XmlDocument doc = new XmlDocument();
doc.LoadXml(soapBodyString);
if (doc.GetElementsByTagName("Ticket").Item(0).InnerText == "")
{
throw new SecurityException("Neplatny uzivatel");
}
else
{
return doc.GetElementsByTagName("Ticket").Item(0).InnerText;
}
}
}
我在Soap扩展类中使用了CryptUtility类:
public class SoapMsg : SoapExtension
{
private CryptUtility cryptUtil = null;
string GUID;
//...
public override void Initialize(object initializer)
{
SoapMsgAttribute attribute =
initializer as SoapMsgAttribute;
soapElement = attribute.SoapElementArray;
//create instance
cryptUtil = new CryptUtility();
}
//copy stream method
private void CopyStream(Stream from, Stream to)
{
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.Write(reader.ReadToEnd());
writer.Flush();
}
private void DecryptMessage()
{
using (MemoryStream copyOldStream = new MemoryStream())
{
CopyStream(oldStream, copyOldStream);
copyOldStream.Position = 0;
using (Stream retStream = cryptUtil.DecryptAndVerifySingXml(copyOldStream)
{
retStream.Position = 0; // < == in this place is bug !!! line 183.
newStream.Position = 0;
CopyStream(retStream, newStream);
newStream.Position = 0;
}
}
}
public override void ProcessMessage(SoapMessage message)
{
switch (message.Stage)
{
case SoapMessageStage.BeforeSerialize:
break;
case SoapMessageStage.AfterSerialize:
{
}
break;
case SoapMessageStage.BeforeDeserialize:
{
using (MemoryStream tempStream = new MemoryStream())
{
CopyStream(oldStream, tempStream);
tempStream.Position = 0;
GUID = cryptUtil.GetGuid(tempStream);
oldStream.Position = 0;
// call method, in which is bug
DecryptMessage();
}
break;
case SoapMessageStage.AfterDeserialize:
break;
default:
throw new ArgumentException("error");
}
}
}
}
在BeforeDeserialize的ProcessMessage中我调用方法DecryptMessage()就是bug。在客户端肥皂扩展完成此错误:
System.Web.Services.Protocols.SoapException:服务器无法处理请求。 ---&GT; System.ObjectDisposedException:无法访问已关闭的Stream。 在System.IO .__ Error.StreamIsClosed()
错误符合要求 : retStream.Position = 0; //&lt; ==在这个地方是bug !!!第183行。 在DecryptMessage()方法中。
首先我使用谷歌,但我没有找到此错误的解决方案。有人可以帮帮我吗?
答案 0 :(得分:4)
问题是你正在处理然后返回的流 - 所以调用者将无法使用它。
删除您返回的流的using
语句。你也没有在第一个块中使用流,你可以摆脱“其他”。以下是包含这些更改的完整DecryptVerifySignXml
方法:
public virtual Stream DecryptAndVerifySignXml(Stream inputStream)
{
XmlDocument doc = new XmlDocument();
using (XmlTextReader reader = new XmlTextReader(inputStream))
{
doc.Load(reader);
}
//.....crypt and verify sing
if (!signedXml.CheckSignature(Key))
{
throw new SecurityException("error");
}
MemoryStream retStream = new MemoryStream();
doc.Save(retStream);
retStream.Position = 0; // Rewind so it's ready to use
return retStream;
}
(我不确定该方法的名称是否特别有效,我不得不说 - 该方法没有进行任何解密而且它没有签署任何内容 - 它只是加载一些XML并检查现有签名。无论如何,这是由...)
然而,您的CopyStream
方法已被破坏 - 它假设内容是UTF-8编码的文本。在某些情况下可能是这样,但不是全部。你应该使用这样的东西:
static void CopyStream(Stream input, Stream output)
{
byte[] buffer = new byte[8192];
int bytesRead;
while ((bytesRead = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, bytesRead);
}
}
答案 1 :(得分:2)
从using
声明中删除retStream
;所以改变这个
using (MemoryStream retStream = new MemoryStream())
用这个
MemoryStream retStream = new MemoryStream();