2

I have avoided using and have not closed the Stream after reading several posts in StackOverflow but still keep getting the error:

Cannot access a closed Stream.

Here is my asp.net core middleware I wrote to decrypt the incoming payload and override the HttpContext.Request.Body with the decrypted string.

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

And the Error I am getting is:

{
    "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"
}

Am I doing something wrong here? Can't figure it out.

2
  • 1
    Why are you disposing a request body await httpContext.Request.Body.DisposeAsync();? Without buffering the request can be read only once Commented Dec 8, 2020 at 14:46
  • 1
    You can see this thread may helpful. Commented Dec 9, 2020 at 2:46

1 Answer 1

2

seems you are disposing the StreamWriter sw, which in turn will dispose the memory stream passed to it

try using this

 public static Stream GenerateStreamFromString(string s)
  {
     var ms = new MemoryStream(Encoding.Default.GetBytes(s));
     return ms;
  }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.