使用和流

时间:2009-10-18 12:37:13

标签: c# .net stream

我在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()方法中。

首先我使用谷歌,但我没有找到此错误的解决方案。有人可以帮帮我吗?

2 个答案:

答案 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();