来自 OnTokenValidated 事件侦听器的 TokenValidatedContext 的安全令牌缺少最后一个字符串段

Security token from TokenValidatedContext from the OnTokenValidated event listener is missing last string segment

我正在为我的 .NET Core 项目使用 Microsoft.AspNetCore.Authentication.JwtBearerSystem.IdentityModel.Tokens.Jwt

每当我生成一个新令牌时,我都会将其存储到数据库中。首先,这是我生成新令牌的方式

    public string GenerateToken(Dictionary<string, object> payload)
    {
        DateTime tokenExpiresAt = DateTime.Now.AddMilliseconds(1); // from config
        byte[] symmetricKey = Convert.FromBase64String("secret"); // from config
        SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
    
        SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
        {
            Claims = payload,
            Expires = tokenExpiresAt,
            SigningCredentials = new SigningCredentials(symmetricSecurityKey, 
                SecurityAlgorithms.HmacSha256Signature)
        };
    
        JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
        SecurityToken securityToken = tokenHandler.CreateToken(tokenDescriptor);
        string token = tokenHandler.WriteToken(securityToken);

        return token;
    }

生成的示例令牌是

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwibmJmIjoxNTk1NDQ1NjMxLCJleHAiOjE1OTU0NDU2OTEsImlhdCI6MTU5NTQ0NTYzMX0.cWvSpKC_yYao2_ziW_ahjjHpUl2SgUZvCmsjXntxCOI

如果客户端尝试访问受保护的端点,默认配置将处理基本验证(在启动文件的 DI 设置中配置)

        services
            .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(jwtBearerOptions =>
            {
                byte[] symmetricKey = Convert.FromBase64String("secret"); // from config
                SymmetricSecurityKey symmetricSecurityKey = new SymmetricSecurityKey(symmetricKey);
                
                jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters()
                {
                    ValidateIssuerSigningKey = true,
                    ValidateLifetime = true,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    IssuerSigningKey = symmetricSecurityKey,
                };

                jwtBearerOptions.Events = new JwtBearerEvents()
                {
                    OnTokenValidated = ProcessAfterTokenValidation
                };
            });

如您所见,我向 OnTokenValidated 事件侦听器添加了一个方法。此方法应检查令牌是否存在于数据库中。

    public async Task ProcessAfterTokenValidation(TokenValidatedContext tokenValidatedContext)
    {
        JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
        string token = jwtSecurityTokenHandler.WriteToken(tokenValidatedContext.SecurityToken);
        
        // ... check if token exists in db ...
    }

该方法的问题是生成的令牌与存储在数据库中的令牌不完全相同。缺少最后一段。 token 变量持有这个

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXIxIiwibmJmIjoxNTk1NDQ1NjMxLCJleHAiOjE1OTU0NDU2OTEsImlhdCI6MTU5NTQ0NTYzMX0.

缺少的最后一部分是

cWvSpKC_yYao2_ziW_ahjjHpUl2SgUZvCmsjXntxCOI

有人知道为什么缺少令牌的最后一部分吗?

感谢您的帮助!

令牌的最后一部分是签名。 OnTokenValidated 方法的目的是提供一个 ClaimsIdentity。签名不是令牌持有者声明的组成部分。

如果您在发行方有密钥轮换政策,则给定用户可以在密钥轮换前后使用不同的签名提出相同的声明。

用户的身份来自发行者的组合以及任何可识别用户的声明(例如,您示例中令牌中的 username)。

在您的情况下,由于您是发行者,减去签名的令牌仅表示用户已成功通过您的令牌发行端点进行身份验证的证据。令牌中的声明应指向数据库记录而不是令牌本身。