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

ECDsa实例二次导入私钥触发ObjectDisposedException问题求助

解决ECDsa实例Dispose后重新导入同一私钥抛出ObjectDisposedException的问题

问题分析

你的代码核心问题在于JwtSigningKeyProvider中复用了同一个ECDsa实例,并在每次调用Get()时重复导入私钥;同时ECDsaSecurityKey会持有该ECDsa实例的强引用,结合JsonWebTokenHandler的内部处理逻辑,当第一个实例被Dispose后,第二次创建的新实例可能被底层残留的已释放引用干扰,导致抛出异常。

可行解决方案

以下两种方案均可解决该问题:

方案1:构造时一次性导入私钥,避免重复导入

修改JwtSigningKeyProvider,在构造函数中完成私钥导入,后续Get()直接返回已初始化的密钥:

using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using System.Security.Cryptography;

namespace ECDsaDisposeBug;

public class JwtSigningKeyProvider : IDisposable
{
    const string privateKeyBase64 = "MIHcAgEBBEIAsukFBinjgL9KONxPRvunQGdaTEhIL9JpwlgW0NN0XzlmbENucgw4XTczjyjlF9AnJnJHg8vXoM2bH5MJy+42OeegBwYFK4EEACOhgYkDgYYABAF8Nt5oxNZ9VwQzjPCWai7/p8hI6sbCAQI8wDcWfQ2Cddrw4G7v5wu6+z26hGJSJY66wKl0ar4fN+JrbCMIYS9UugHAs3W75a/KtiNfVJ9tYwFM0CYWP2kAKg7Kbk3SXkXMW4Gdb4XeoDO+TQVTRfWoBYXXx1iVu0dOXv5NkGZFIkKAHg==";
    readonly ECDsa _algorithm;
    readonly ECDsaSecurityKey _securityKey;

    public JwtSigningKeyProvider()
    {
        _algorithm = ECDsa.Create();
        var privateKey = Convert.FromBase64String(privateKeyBase64);
        _algorithm.ImportECPrivateKey(new ReadOnlySpan<byte>(privateKey), out _);
        _securityKey = new ECDsaSecurityKey(_algorithm);
    }

    public AsymmetricSecurityKey Get()
    {
        return _securityKey;
    }

    public void Dispose()
    {
        _algorithm.Dispose();
        GC.SuppressFinalize(this);
    }
}

方案2:每次调用Get()时创建新的ECDsa实例

如果需要动态切换密钥,可以每次创建独立的ECDsa实例,避免实例间的干扰:

using Microsoft.IdentityModel.JsonWebTokens;
using Microsoft.IdentityModel.Tokens;
using System.Collections.Generic;
using System.Security.Cryptography;

namespace ECDsaDisposeBug;

public class JwtSigningKeyProvider : IDisposable
{
    const string privateKeyBase64 = "MIHcAgEBBEIAsukFBinjgL9KONxPRvunQGdaTEhIL9JpwlgW0NN0XzlmbENucgw4XTczjyjlF9AnJnJHg8vXoM2bH5MJy+42OeegBwYFK4EEACOhgYkDgYYABAF8Nt5oxNZ9VwQzjPCWai7/p8hI6sbCAQI8wDcWfQ2Cddrw4G7v5wu6+z26hGJSJY66wKl0ar4fN+JrbCMIYS9UugHAs3W75a/KtiNfVJ9tYwFM0CYWP2kAKg7Kbk3SXkXMW4Gdb4XeoDO+TQVTRfWoBYXXx1iVu0dOXv5NkGZFIkKAHg==";
    readonly List<ECDsa> _algorithms = new List<ECDsa>();

    public AsymmetricSecurityKey Get()
    {
        var algorithm = ECDsa.Create();
        _algorithms.Add(algorithm);
        var privateKey = Convert.FromBase64String(privateKeyBase64);
        algorithm.ImportECPrivateKey(new ReadOnlySpan<byte>(privateKey), out _);
        return new ECDsaSecurityKey(algorithm);
    }

    public void Dispose()
    {
        foreach (var alg in _algorithms)
        {
            alg.Dispose();
        }
        _algorithms.Clear();
        GC.SuppressFinalize(this);
    }
}

说明

两种方案均通过避免重复复用已释放实例的引用,消除了ObjectDisposedException的触发条件。方案1更适合固定密钥的场景,性能更优;方案2则适用于需要动态生成密钥的场景。

内容的提问来源于stack exchange,提问作者Doug Clutter

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 03:57:05