【问题标题】:JwtSecurityTokenHandler().WriteToken(token) throwing error in hosted environmentJwtSecurityTokenHandler().WriteToken(token) 在托管环境中抛出错误
【发布时间】:2021-11-10 18:27:28
【问题描述】:

我有一个 .NET 5 项目。我正在尝试在其中生成 JWT。这一行给我一个部署到 IIS Web 服务器的错误:JwtSecurityTokenHandler().WriteToken(token)

The encryption algorithm 'System.String' requires a key size of at least 'System.Int32' bits.
Key 'Microsoft.IdentityModel.Tokens.SymmetricSecurityKey', is of size: 'System.Int32'. (Parameter 'key')

我在其中添加了注释代码,以测试进入令牌生成的值是否正常,并且密钥长度为 16 个字符(我已经测试了更多但仍然失败)。

这在我的本地环境中运行良好。

有人知道为什么会这样吗?

var claims = new[]
{
    new Claim(JwtRegisteredClaimNames.Sub, user.Id),
    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};

var key = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_jwtConfig.Value.SecretKey));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);

var token = new JwtSecurityToken(_jwtConfig.Value.Issuer,
    _jwtConfig.Value.Audience,
    claims,
    expires: DateTime.UtcNow.AddDays(30),
    signingCredentials: creds);

//return new JsonResult(new Dictionary<string, object>
//  {
//    { "secretkey", _jwtConfig.Value.SecretKey },
//    { "creds", creds.ToString() },
//    { "issuer", _jwtConfig.Value.Issuer },
//    { "audience", _jwtConfig.Value.Audience },
//    { "token", token.ToString() }
//  });


return new JsonResult(new Dictionary<string, object>
    {
      { "access_token", new JwtSecurityTokenHandler().WriteToken(token) },
    });

来自Startup.cs的相关部分:

services.Configure<JWTSettings>(Configuration.GetSection("JWTSettings"));

services.AddAuthentication()
    .AddCookie()
    .AddJwtBearer(options =>
    {
        options.RequireHttpsMetadata = false;
        options.IncludeErrorDetails = true;

        var secretKey = Configuration.GetSection("JWTSettings:SecretKey").Value;
        var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey));

        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = Configuration.GetSection("JWTSettings:Issuer").Value,
            ValidateAudience = true,
            ValidAudience = Configuration.GetSection("JWTSettings:Audience").Value,
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = signingKey,

        };

    })

【问题讨论】:

  • _jwtConfig.Value.SecretKey 的值是多少?似乎价值来自当地环境。启动文件中secretKey的长度是多少? var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(secretKey))
  • 它的长度超过 16 个字符 @BruceZhang 是 HmacSHA256 所必需的,从 appsettings.json 文件中提取。当我取消注释注释部分时(我将其放入以便我可以看到它通过了什么),我可以看到它是正确的值。

标签: c# .net iis jwt .net-5


【解决方案1】:

这似乎不是编码问题,更多的是网络主机的 .NET 配置。将应用程序部署为“框架依赖”会导致错误,但是“自包含”代码本身可以工作。

【讨论】:

    【解决方案2】:

    您似乎有错误IDX10653

    但您的异常消息未显示真实信息。请查看此article 了解详情。能否添加代码IdentityModelEventSource.ShowPII = true; 并提供真实的异常信息?

    我想你会看到真正的异常信息并且你可以理解发生了什么。 您的 SecretKey 很可能少于 128 位。在这种情况下,只需尝试在配置文件中为参数JWTSettings:SecretKey 使用更长的值。所以here描述了类似的场景。

    【讨论】:

      【解决方案3】:

      好的,我可能有解决方案,但我不太确定,如果可行,请告诉我:

      我已经像这样直接在 Startup.cs 中配置了我的 JWT 令牌:

      Startup.cs

      public static void AddIdentityServices(this IServiceCollection services, IConfiguration configuration)
          {
              services.Configure<JwtSettings>(configuration.GetSection("JwtSettings"));
      
              // Identity stuff
      
              services.AddTransient<IAuthenticationService, AuthenticationService>();
      
              services.AddAuthentication(options =>
              {
                  options.DefaultAuthenticateScheme = "JwtBearer";
                  options.DefaultChallengeScheme = "JwtBearer";
              })
                  .AddJwtBearer("JwtBearer", o =>
                  {
                      o.RequireHttpsMetadata = false;
                      o.SaveToken = true;
                      o.TokenValidationParameters = new TokenValidationParameters
                      {
                          ValidateIssuerSigningKey = true,
                          ValidateIssuer = false,
                          ValidateAudience = false,
                          ValidateLifetime = true,
                          ValidIssuer = configuration["JwtSettings:Issuer"],
                          ValidAudience = configuration["JwtSettings:Audience"],
                          ClockSkew = TimeSpan.FromMinutes(5),
                          IssuerSigningKey = new SymmetricSecurityKey(
                              Encoding.UTF8.GetBytes(configuration["JwtSettings:Key"]))
                      };
      
                      o.Events = new JwtBearerEvents()
                      {
                          OnAuthenticationFailed = c =>
                          {
                              c.NoResult();
                              c.Response.StatusCode = 500;
                              c.Response.ContentType = "text/plain";
                              return c.Response.WriteAsync($"{c.Exception.ToString()} JwtBearerEvents in IdentityServiceRegistration");
                          },
                          OnChallenge = context =>
                          {
                              context.HandleResponse();
                              context.Response.StatusCode = 401;
                              context.Response.ContentType = "application/json";
                              var result = JsonConvert.SerializeObject("401 Not authorized");
                              return context.Response.WriteAsync(result);
                          },
                          OnForbidden = context =>
                          {
                              context.Response.StatusCode = 403;
                              context.Response.ContentType = "application/json";
                              var result = JsonConvert.SerializeObject("403 Not authorized");
                              return context.Response.WriteAsync(result);
                          },
                      };
                  });
          }
      

      这是我的 CreateUserAsync 和其他方法使用的令牌生成方法:

      private async Task<JwtSecurityToken> GenerateToken(ApplicationUser user)
          {
              var claims = new[]
              {
                  new Claim(ClaimTypes.Name, user.UserName),
                  new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                  new Claim(ClaimTypes.Email, user.Email),
                  new Claim(ClaimTypes.NameIdentifier, user.Id),
                  new Claim(JwtRegisteredClaimNames.Nbf,
                      new DateTimeOffset(DateTime.Now).ToUnixTimeSeconds().ToString()),
                  new Claim(JwtRegisteredClaimNames.Exp,
                      new DateTimeOffset(DateTime.Now.AddYears(10))
                      .ToUnixTimeSeconds().ToString())
              }
              .Union(userClaims);
      
              var jwtSecurityToken = new JwtSecurityToken(
                  new JwtHeader(
                      new SigningCredentials(
                          new SymmetricSecurityKey(Encoding.UTF8.GetBytes("//secret key of 64 characters of capital letters and numbers")),
                          SecurityAlgorithms.HmacSha256)),
                  new JwtPayload(claims));
      
              return jwtSecurityToken;
          }
      

      您应该能够从这样的网站生成密钥:SHA256 Generator

      如果有帮助,请告诉我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-15
        • 2015-04-05
        • 2018-01-24
        • 1970-01-01
        • 2021-11-21
        • 2013-11-27
        • 1970-01-01
        • 2011-10-10
        相关资源
        最近更新 更多