c# - 不断收到错误 : Cannot access a closed Stream on Asp.net Core 中间件

标签 c# asp.net-core stream middleware

在阅读 StackOverflow 中的几篇文章后,我已经避免使用 using 并且没有关闭 Stream,但仍然不断收到错误:

Cannot access a closed Stream.

这是我编写的 asp.net core 中间件,用于解密传入的有效负载并使用解密的字符串覆盖 HttpContext.Request.Body

public class DecryptMiddleware
    {
        private readonly RequestDelegate _next;
        private X509Certificate2 cert;
        public DecryptMiddleware(RequestDelegate next)
        {
            cert = new X509Certificate2(@"C:\Program Files\OpenSSL-Win64\bin\SandBox\07122020\my-cert.pfx", "xxxxxxxx");
            _next = next;
        }

        public async Task InvokeAsync(HttpContext httpContext)
        {
            
            //body => stream
            var encryptedRequestData = httpContext.Request.Body;
            var encryptedAttributeData = string.Empty;
            var decryptedResponseData = String.Empty;

            if (httpContext.Request.Method == "POST") 
            {

                //DeSerialize
                var encryptedData = string.Empty;
                StreamReader stream = null;
                try
                {
                    stream = new StreamReader(encryptedRequestData);
                    var body = await stream.ReadToEndAsync();
                    var request = JsonConvert.DeserializeObject<SecureTestClass>(body);
                    encryptedData = request.JData;
                }
                finally
                {
                    if (stream != null) //I tried avoiding this code but still keep getting the error
                    {
                        stream.Close();
                        stream.Dispose();
                    }
                }
                

                //Decrypt
                var rsa = (RSACng)cert.PrivateKey;
                decryptedResponseData = Encoding.UTF8.GetString(
                    rsa.Decrypt(Convert.FromBase64String(encryptedData)
                                , RSAEncryptionPadding.Pkcs1)
                    );
                

                httpContext.Request.Body = GenerateStreamFromString(decryptedResponseData);
            }
            
            await _next(httpContext);
            await httpContext.Request.Body.DisposeAsync();
        }

        public static Stream GenerateStreamFromString(string s)
        {
            StreamWriter sw = null;
            StreamReader sr = null;
            MemoryStream ms = null;

            try
            {
                ms = new MemoryStream();
                sw = new StreamWriter(ms);
                sr = new StreamReader(ms);

                sw.WriteLine(s);
                ms.Position = 0;
            }            
            finally
            {
                if (sw != null) sw.Dispose();
                if (sr != null) sr.Dispose();
            }

            return ms;
        }
    }

我得到的错误是:

{
    "Message": "Cannot access a closed Stream.",
    "Exception": "System.ObjectDisposedException: Cannot access a closed Stream.\r\n   at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n   at System.IO.MemoryStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)\r\n   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n   at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)\r\n   at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)\r\n   at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\r\n   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n   at BankServiceListener.Middleware.DecryptMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DecryptionMiddleware.cs:line 69\r\n   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n   at BankServiceListener.Middleware.DeveloperExceptionMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DeveloperExceptionMiddleware.cs:line 27",
    "StackTrace": "   at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)\r\n   at System.IO.MemoryStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Text.Json.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken)\r\n   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n   at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding)\r\n   at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext)\r\n   at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)\r\n   at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)\r\n   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)\r\n   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)\r\n   at BankServiceListener.Middleware.DecryptMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DecryptionMiddleware.cs:line 69\r\n   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)\r\n   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)\r\n   at BankServiceListener.Middleware.DeveloperExceptionMiddleware.InvokeAsync(HttpContext httpContext) in C:\\Projects\\GIT\\JKSB\\BankServiceListener\\BankServiceListener\\Middleware\\DeveloperExceptionMiddleware.cs:line 27",
    "Source": "System.Private.CoreLib"
}

我在这里做错了什么吗?想不通。

最佳答案

似乎您正在处置 StreamWriter sw,而 StreamWriter sw 又将处置传递给它的内存流

尝试使用这个

 public static Stream GenerateStreamFromString(string s)
  {
     var ms = new MemoryStream(Encoding.Default.GetBytes(s));
     return ms;
  }

关于c# - 不断收到错误 : Cannot access a closed Stream on Asp.net Core 中间件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65200658/

相关文章:

java - java中如何将数据从一个对象列表复制到另一个对象列表?

java - 从 DataInputStream 读取几个 byte[]

c# - 在 Unity3d 中为 VR 360 度图像应用更改聚焦球体的 Material

c# - 如何将表达式树转换为部分 SQL 查询?

c# - 按名称对文件进行排序,与 C# 中的 Windows 相同

c# - “Data.Repository.UnitofWork”未实现接口(interface)成员 'Data.Repository.IUnitofWork.Customer'

azure - 将 netcoreapp1.1 部署到 Azure

c# - .NET Core 2.1 API Post Controller 返回无效输入

asp.net - 如何在 ASP.NET Core MVC 1.0 中创建和管理插件?

c++ - 只要应用程序运行就一直打开错误日志是否可以接受?