.Net Core 2.2 验证 jwt 在容器上失败并显示 401 [英] .Net Core 2.2 Validation of jwt failing with 401 on a container

查看:65
本文介绍了.Net Core 2.2 验证 jwt 在容器上失败并显示 401的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在 .net core 2.2 中,当我容器化应用程序时,我收到一个 Bearer error="invalid_token", error_description="The signature is invalid"

In .net core 2.2 when i containerize the app i get a Bearer error="invalid_token", error_description="The signature is invalid"

当我使用 IIS/IIS express 在 Windows 上托管它时它工作正常.

It is working fine when i host it on windows using IIS/IIS express.

我的代码 -- 令牌生成器是 IBM API Connect,它使用 RSA 256 算法生成密钥

My code -- The token generator is IBM API Connect it uses RSA 256 Algorithm to generate the key

 var rsa = new RSACryptoServiceProvider();
 string exponentvalue = "AQAB";
 var e = Base64UrlEncoder.DecodeBytes(exponentvalue);
 var N = "public key  put your value here"
 var modulus = Base64UrlEncoder.DecodeBytes(N);
 rsa.ImportParameters(
     new RSAParameters()
     {
             Modulus = modulus,
             Exponent = e
    });
  var signingKey = new RsaSecurityKey(rsa);

var tokenValidationParameters = new TokenValidationParameters
          {
              // The signing key must match!
              ValidateIssuerSigningKey = true,
              IssuerSigningKey = signingKey,

              // Validate the JWT Issuer (iss) claim
              ValidateIssuer = false,
              ValidIssuer = issuer,

              // Validate the JWT Audience (aud) claim
              ValidateAudience = false,
              ValidAudience = audience,

              // Validate the token expiry
              //ValidateLifetime = true,

              // If you want to allow a certain amount of clock drift, set that here:
              //ClockSkew = TimeSpan.FromMinutes(1)
          };

知道为什么它不能在本地托管在 docker 或 AKS 上的容器上工作吗?

Any idea why it wouldn't be working on a container hosted either locally on docker or AKS?

推荐答案

经过几天的研究和尝试不同的东西终于解决了我的问题.

After few days of researching and trying different things have finally Resolved my issue.

@bartonjs 在这里提到了第一个问题 在 .NET 核心中实现 RSA 我不得不使用 RSA.Create() 而不是 RSACryptoServiceProvider().

First Issue was as mentioned by @bartonjs here implement RSA in .NET core I had to use RSA.Create() Instead of RSACryptoServiceProvider().

上面帖子中推荐的第二个问题我正在使用(使用)语句实现它,但在 Linux 中不起作用.来自 @bartonjs 对这篇文章的评论 https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/994 看起来像是引入了一个错误我们可能不小心引入了一个错误,其中 post-dispose 与新创建的相同,在那里它认为它只需要在第一次(在本例中为下一步)使用时补上一个键即可."

Second Issue as recommended in above post i was implementing it with (using) statement which was not working in Linux. From @bartonjs comments on this post https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/994 it looks like a bug introduced "We might have accidentally introduced an error where post-dispose is the same as freshly created, where it thinks it needs to just make up a key on first (next, in this case) use."

适用于 Linux 和 Windows 的最终代码

Final code that works both on Linux and Windows

public class JwtConfiguration : IDisposable
    {
        /// <summary>
        /// Configures the JWT Token Validation parameters.
        /// </summary>
        /// <param name="Configuration">
        /// ASP.NET Core Configuration object instance.
        /// </param>
        /// <returns>
        /// A TokenValidationParameters object instance.
        /// </returns>
        private RSA _publicRsa;
        private SecurityKey _issuerSigningKey;

        public TokenValidationParameters GetTokenValidationParameters(IConfiguration Configuration)
        {

            var issuer = Configuration["Jwt:Issuer"];
            if (string.IsNullOrWhiteSpace(issuer))
            {
                throw new MissingJwtTokenParameterException("Missing Jwt:Issuer value.");
            }

            var audience = Configuration["Jwt:Audience"];
            if (string.IsNullOrWhiteSpace(audience))
            {
                throw new MissingJwtTokenParameterException("Missing Jwt:Audience value.");
            }

            var secretKey = Configuration["Jwt:Key"];
            if (string.IsNullOrWhiteSpace(secretKey))
            {
                throw new MissingJwtTokenParameterException("Missing Jwt:Key value.");
            }

            string exponentvalue = "AQAB";
            var e = Base64UrlEncoder.DecodeBytes(exponentvalue);
            var modulus = Base64UrlEncoder.DecodeBytes(secretKey);
            _publicRsa = RSA.Create();
            _publicRsa.KeySize = 3072;
            _publicRsa.ImportParameters(
            new RSAParameters()
            {
                Modulus = modulus,
                Exponent = e
            });

            _issuerSigningKey = new RsaSecurityKey(_publicRsa);

            var tokenValidationParameters = new TokenValidationParameters
            {
                // The signing key must match!
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = _issuerSigningKey,

                // Validate the JWT Issuer (iss) claim
                ValidateIssuer = true,
                ValidIssuer = issuer,

                // Validate the JWT Audience (aud) claim
                ValidateAudience = true,
                ValidAudience = audience,

                //Validate the token expiry
                ValidateLifetime = true,

                // If you want to allow a certain amount of clock drift, set that here:
                ClockSkew = TimeSpan.FromMinutes(1)
            };

            return tokenValidationParameters;

        }



        #region IDisposable Support
        private bool disposedValue = false; // To detect redundant calls

        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    // TODO: dispose managed state (managed objects).
                    _publicRsa?.Dispose();
                }

                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.

                disposedValue = true;
            }
        }

        // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
         ~JwtConfiguration() {
           // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
           Dispose(false);
         }

        // This code added to correctly implement the disposable pattern.
        public void Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose(true);
            // TODO: uncomment the following line if the finalizer is overridden above.
            GC.SuppressFinalize(this);
        }
        #endregion

    }

这篇关于.Net Core 2.2 验证 jwt 在容器上失败并显示 401的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆