You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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注入的过滤器:

    1. 创建实现IAsyncAuthorizationFilter的类(如CustomAuthorizationFilter)
    2. 在Program.cs中注册为Scoped:builder.Services.AddScoped<CustomAuthorizationFilter>()
    3. 用[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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:42:10