Jwt 令牌如何工作以及错误代码 IDX12709

How does the Jwt tokens work and Errorcode IDX12709

我实现了一个Github项目,不明白Jwt的用户和密钥系统是如何工作的。 我现在有一个位于 AppSettings 中的密钥,当用户登录时,将执行以下功能:

private string GenerateJwtToken(string username)
{
   var tokenHandler = new JwtSecurityTokenHandler();
   var key = Encoding.ASCII.GetBytes(_appSettings.token);
   var tokenDescriptor = new SecurityTokenDescriptor
   {
      Subject = new ClaimsIdentity(new[] { new Claim("username", username) }), //<-
      Expires = DateTime.UtcNow.AddMinutes(30),
      SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
   };
   var token = tokenHandler.CreateToken(tokenDescriptor);
   return tokenHandler.WriteToken(token);
}

因此,如果我做对了,那么我会在这里为登录用户生成令牌,但是带有用户名的那一行是什么意思? 之后,我将用户名和令牌存储在 sessionStorage 中,如果我在定义了 [Authorize] 属性的地方触发了其他一些 Controller,我会添加 followed Header 和 fetch:

headers: {
   'Content-type': 'application/json',
   'Authorization': `Bearer ${sessionStorage.getItem("token")}`,
},

然后它先运行进入这个函数:

public async Task Invoke(HttpContext context, IAuthService authService)
{
   var token = context.Request.Headers["Authorization"].FirstOrDefault()?.Split(" ").Last();
   if (token != null)
      attachUserToContext(context, authService, token);
   await _next(context);
}

private void attachUserToContext(HttpContext context, IAuthService authService, string token)
{
   try
   {
      var tokenHandler = new JwtSecurityTokenHandler();
      var key = Encoding.ASCII.GetBytes(_appSettings.Secret);
      tokenHandler.ValidateToken(token, new TokenValidationParameters //<- Error
      {
         ValidateIssuerSigningKey = true,
         IssuerSigningKey = new SymmetricSecurityKey(key),
         ValidateIssuer = false,
         ValidateAudience = false,
         ClockSkew = TimeSpan.Zero
      }, out SecurityToken validatedToken);
      var jwtToken = (JwtSecurityToken)validatedToken;
      var userId = int.Parse(jwtToken.Claims.First(x => x.Type == "username").Value);
      context.Items["User"] = "user";
   }
   catch
   {
      // do nothing if jwt validation fails
      // user is not attached to context so request won't have access to secure routes
   }
}

所以在这里它验证 Header 中的 token 不为空然后它尝试做什么!?还有为什么这里又用了用户名?

当它 运行 ValidateToken 运行它时 return 一个错误:IDX12709: CanReadToken() returned false。 JWT 格式不正确:'['System.String' 类型的 PII 已隐藏

https://github.com/cornflourblue/dotnet-5-jwt-authentication-api/tree/279c8058669bbfa59902a4473f62e5371167340c

JWT 分为三个部分。 第一个是 header,其中包含加密算法等信息。 第二部分是有效负载,您实际上可以在其中找到您的声明,在您的情况下,它将是用户名、到期日、 你可以在这里添加任何你需要的。 这里添加唯一的用户名或id,让服务器知道这个token属于谁,谁在调用服务器。 在其他情况下,您将如何确定谁在调用服务器,您必须将此令牌保存在某个数据库中或与分配的用户一起保存在某个地方。 最后一部分是签名,这部分是用你的密钥验证的,知道它不是什么假令牌,而实际上是你创建的令牌。 部分由点分割。

很难说为什么你的令牌验证失败,首先我会尝试检查你在 https://jwt.io 上创建的令牌并看看里面有什么。 也许您使用不记名前缀验证令牌,因为上面写着令牌格式不正确,所以这可能是问题所在。

除了使用自定义中间件身份验证之外,还可以使用 JWT 默认身份验证方案

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = false,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII
                        .GetBytes(Configuration.GetSection("AppSettings:Token").Value)),
                    //...
                };
            });