首页 > 解决方案 > 在 RSA 类上使用语句会导致 401 / 对象被过早处理?

问题描述

我目前遇到了使用公钥解密 jwts 的问题。当我使用带有 using 声明的 RSA 类时(为了安全起见,我也尝试了较旧的语法),每次都会得到 401。删除 using 关键字可以解决问题,但我确信这是不好的做法,因为 RSA 是 IDisposable。关于如何以正确的方式进行这项工作的任何想法?

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
{
    var publicKey = tokenSettings.PublicKey.ToByteArray();
        
    // removing "using" makes it work
    using var rsa = RSA.Create();
    rsa.ImportSubjectPublicKeyInfo(publicKey, out _);
    var key = new RsaSecurityKey(rsa);
            
    opt.TokenValidationParameters = new TokenValidationParameters
    {
        IssuerSigningKey = key,
        ValidAudience = tokenSettings.TargetAud,
        ValidIssuers = new[] { tokenSettings.Issuer },
        RequireSignedTokens = true,
        RequireExpirationTime = true,
        ValidateLifetime = true,
        ValidateAudience = true,
        ValidateIssuer = true,
        ClockSkew = TimeSpan.Zero,     
    };
});

我确实在这里找到了一个自我回答RSA Disposed Object Error - every other test,但没有省略“使用” IDisposable 对象的不正确使用?

我还要注意,这与缓存问题不同,后者返回 200 一次,然后返回 401。该代码当前每次都返回 401。

标签: c#asp.netjwtusingidisposable

解决方案


如何在大括号中设置 using-clause,这样它就不会在下一条指令后被处理?

services.AddAuthentication(Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(opt =>
{
    System.ReadOnlySpan<byte> publicKey = tokenSettings.PublicKey.ToByteArray();

    // removing "using" makes it work
    using (System.Security.Cryptography.RSA rsa = System.Security.Cryptography.RSA.Create())
    {
        rsa.ImportSubjectPublicKeyInfo(publicKey, out _);
        Microsoft.IdentityModel.Tokens.RsaSecurityKey key = new Microsoft.IdentityModel.Tokens.RsaSecurityKey(rsa);

        opt.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
        {
            IssuerSigningKey = key,
            ValidAudience = "tokenSettings.TargetAud",
            ValidIssuers = new[] { "tokenSettings.Issuer" },
            RequireSignedTokens = true,
            RequireExpirationTime = true,
            ValidateLifetime = true,
            ValidateAudience = true,
            ValidateIssuer = true,
            ClockSkew = System.TimeSpan.Zero,
        };
    }
});

但最有可能的是,这是因为 RsaSecurityKey 包含 RSA-Provider 的实例,并使用它来加密和解密 JWT-Bearer。如果 RSA 实例被处置,这有点问题......

//
// Zusammenfassung:
//     Represents a Rsa security key.
public class RsaSecurityKey : AsymmetricSecurityKey
{
    public RsaSecurityKey(RSAParameters rsaParameters);
    public RsaSecurityKey(RSA rsa);

    [Obsolete("HasPrivateKey method is deprecated, please use PrivateKeyStatus.")]
    public override bool HasPrivateKey { get; }
    public override PrivateKeyStatus PrivateKeyStatus { get; }


    public RSA Rsa { get; }
}

只需删除使用,RSA 提供程序可能具有应用程序生命周期范围。然而,这适用于多线程......


推荐阅读