使用和流

2023-09-06 09:26:11 作者:隔壁的猪我养的

我调用SOAP扩展其解密和验证唱SOAP消息的方法。 我有这样的类:

I call method in Soap extension which decrypt and verify sing Soap message. I have this classes:

我有类,解密和验证符号SOAP消息,它返回流回来的SOAP扩展类:

I have class, which decrypt and verify sign Soap message, which return stream back in Soap extension class :

方法DecryptAndVerifySingXml和GetGuid使用流从类SOAP扩展。

Method DecryptAndVerifySingXml and GetGuid use stream from class soap extension.

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;
        }

    }
}

我使用类CryptUtility在SOAP扩展类:

I use class CryptUtility in Soap extension class:

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");
            }
        }


    }
 }

在ProcessMessage的在BeforeDeserialize我调用方法DecryptMessage()在至极的错误。在此错误客户端SOAP扩展处理:

In ProcessMessage in BeforeDeserialize I call method DecryptMessage() in wich is bug. On client side soap extension finish with this error :

System.Web.Services.Protocols.SoapException:服务器无法处理请求。 ---> System.ObjectDisposedException:无法访问已关闭的流。    在System.IO .__ Error.StreamIsClosed()

System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.ObjectDisposedException: Cannot access a closed Stream. at System.IO.__Error.StreamIsClosed()

错误是行 :                     retStream.Position = 0; //&LT; ==在这个地方是错误!线183。 在方法DecryptMessage()。

The error is in line : retStream.Position = 0; // < == in this place is bug !!! line 183. in method DecryptMessage().

首先,我用谷歌,但我没有发现这个错误的解决方案。有人可以帮我吗?

First I used google, but I don't find solution for this error. Can somebody help me ?

推荐答案

现在的问题是,你处理的数据流,你再返回 - 所以调用者将无法使用它

The problem is that you're disposing of the stream which you then return - so the caller won't be able to use it.

摆脱使用语句返回的数据流。你还没有使用在第一块流,你可以摆脱的东西。下面是完整 DecryptVerifySignXml 方法,这些变化:

Get rid of the using statements for the streams you return. You're also not using the stream in the first block, and you can get rid of the "else". Here's the complete DecryptVerifySignXml method with these changes:

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和检查现有的签名无论如何,这是由由...)

(I'm not sure the name of the method is particularly valid, I have to say - that method isn't doing any decryption and it's not signing anything - it's just loading some XML and checking an existing signature. Anyway, that's by the by...)

CopyStream 方法是坏了,但是 - 它假定的内容是UTF-8-CN codeD文本。这可能在某些情况下是真实的,但不是全部。你应该使用这样的事情,而不是:

Your CopyStream method is broken, however - it assumes the contents is UTF-8-encoded text. That may be true in some cases, but not all. You should use something like this instead:

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);
    }
}
相关推荐