ASP.NET Core自定义IAsyncAuthorizationFilter引发已释放对象访问错误原因
问题原因分析:Cannot access a disposed object. Object name: 'System.String'
核心原因拆解
特性实例生命周期不匹配
你将特性注册为Scoped服务,但直接在Action上标记[CustomeAttribute]时,框架会自行创建特性实例,而非从DI容器获取。这导致DI注册的Scoped实例与Action上的特性实例是两个独立对象,当DI容器按Scoped生命周期处置资源时,特性中引用的相关对象可能已被释放,后续流程访问时触发错误。请求体流的处置与重置问题
即便启用了请求缓冲,若在OnAuthorizationAsync中读取请求体后未重置流的位置(比如调用ReadAsStringAsync后未将Request.Body.Position设为0),后续Action尝试再次读取请求体时,流可能已被框架标记为处置状态,引发对象释放错误。DTO反序列化的隐性资源绑定
部分序列化器在读取流时会将DTO对象与流资源绑定,当流被处置后,访问DTO的某些属性会触发对已释放流的引用,进而抛出该错误。
解决建议
修正过滤器的使用方式
不要直接在Action上标记特性,改用DI注入的过滤器:- 创建实现
IAsyncAuthorizationFilter的类(如CustomAuthorizationFilter) - 在Program.cs中注册为Scoped:
builder.Services.AddScoped<CustomAuthorizationFilter>() - 用
[ServiceFilter(typeof(CustomAuthorizationFilter))]标记Action,或全局注册过滤器:
builder.Services.AddControllers(options => { options.Filters.Add<CustomAuthorizationFilter>(); });- 创建实现
确保请求体流可重复读取
在过滤器中读取请求体前,显式启用缓冲并重置流位置:await context.HttpContext.Request.EnableBufferingAsync(); var bodyContent = await new StreamReader(context.HttpContext.Request.Body).ReadToEndAsync(); // 重置流位置,供后续流程读取 context.HttpContext.Request.Body.Position = 0; // 用bodyContent字符串反序列化为DTO,避免绑定流资源 var dto = JsonSerializer.Deserialize<YourDto>(bodyContent);隔离序列化与流资源
先将请求体读取为字符串,再基于字符串完成反序列化,避免DTO对象持有对流的引用。
内容的提问来源于stack exchange,提问作者Nour Mawla
相关产品推荐
相关产品推荐

