首页 > 解决方案 > 不断出现错误:无法访问 Asp.net Core 中间件上的已关闭流

问题描述

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

无法访问已关闭的 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"
}

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

标签: c#asp.net-corestreammiddleware

解决方案


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

尝试使用这个

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

推荐阅读