2

如何在 Asp.NetCore WebApi 的 JWT 声明中传递和对象,例如,假设我想传递一个带有 ID 和名称的 Gender 对象。

        private IActionResult GenerateJwtToken(string email, ApplicationUser user)
        {

            var tokenHandler = new JwtSecurityTokenHandler();
            var key = Encoding.ASCII.GetBytes(appSettings.Secret);
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new Claim[] 
                {
                    new Claim(ClaimTypes.Name, user.Id.ToString()),
                    new Claim(ClaimTypes.Email, user.Email.ToString()),
                    new Claim(ClaimTypes.GivenName, user.FirstName.ToString()),
                    new Claim(ClaimTypes.UserData, user.LastName.ToString()),
                    new Claim(ClaimTypes.StreetAddress, user.Address.ToString()),
                    new Claim(ClaimTypes.DateOfBirth, user.DateOfBirth.ToString()),
                    new Claim(ClaimTypes.Rsa, user.FileName.ToString()),
                    new Claim(ClaimTypes.Gender, user.Sex.ToString()),
                    new Claim(ClaimTypes.Country, user.Country.ToString()),
                    new Claim(ClaimTypes.StateOrProvince, user.state.ToString()),
                    new Claim(ClaimTypes.Locality, user.LGA.ToString()),
                    new Claim(ClaimTypes.Hash, user.HairColor.ToString()),
                    new Claim(ClaimTypes.Sid, user.GenoType.Name.ToString()),
                    new Claim(ClaimTypes.Spn, user.BloodGroup.ToString()),
                    new Claim(ClaimTypes.System, user.Religion.ToString()),
                    new Claim(ClaimTypes.NameIdentifier, user.NKName.ToString()),
                    new Claim(ClaimTypes.OtherPhone, user.NKPhoneNumber.ToString()),
                    new Claim(ClaimTypes.SerialNumber, user.NKAddress.ToString()),
                    new Claim(ClaimTypes.GroupSid, user.NKRelationship.ToString()),


                }),

                Expires = DateTime.UtcNow.AddDays(7),
                SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
            };


            var token = tokenHandler.CreateToken(tokenDescriptor);
            var tokenString = tokenHandler.WriteToken(token);

            return Ok(new{ token = tokenString });


        }

请如果有任何更好的方法来获取除了索赔之外的当前登录用户详细信息,我很想知道它。提前致谢

[HttpGet("/api/profile")]
public IActionResult Index()
{
    var claimIdentity = this.User.Identity as ClaimsIdentity;
    IEnumerable<Claim> claims = claimIdentity.Claims;

    var model = new IndexViewModel
    {
        Id = claimIdentity.FindFirst(ClaimTypes.Name).Value,
        Email = claimIdentity.FindFirst(ClaimTypes.Email).Value,
        FirstName = claimIdentity.FindFirst(ClaimTypes.GivenName).Value,
        LastName = claimIdentity.FindFirst(ClaimTypes.UserData).Value,
        Address = claimIdentity.FindFirst(ClaimTypes.StreetAddress).Value,
        DateOfBirth = claimIdentity.FindFirst(ClaimTypes.DateOfBirth).Value,
        FileName = claimIdentity.FindFirst(ClaimTypes.Rsa)?.Value,
    };

    return Ok(model);
}
4

3 回答 3

3

由于声明只能存储字符串值,因此您需要将对象表示为字符串。例如,您可以使用Json.netnuget 包将对象序列化/反序列化为json格式。可能是这样的:

string genderStr = JsonConvert.SerializeObject(gender);
// {
//   "Id": 1,
//   "Name": "Male"
// }
Gender genderObj = JsonConvert.DeserializeObject<Gender>(genderStr);

除了索赔之外,是否有更好的方法来获取当前登录的用户详细信息

正如我所见,您的声明存储在令牌中,可以像您一样从声明中获取它。另一种选择可能是将用户详细信息存储在某些存储中,例如 DB。在这种情况下,您需要从声明中获取用户 ID 并从存储中获取所有详细信息。

这两种选择都值得考虑。使用第一个选项,您将增加令牌大小并减少数据库请求的数量。使用第二个选项,您将减少令牌大小并增加数据库请求的数量。

于 2019-03-12T15:39:57.197 回答
0

我从声明中获取了用户 ID,并像这样从存储中获取了详细信息

[HttpGet("/api/profile")]
public async Task < IActionResult > Index() {

   var userId = caller.Claims.Single(c => c.Type == ClaimTypes.Name);
   var user = await userManager.Users.Include(s => s.Sex)
              .SingleOrDefaultAsync(c => c.Id == userId.Value);

    return Ok(user);

}    
于 2019-03-17T06:49:42.730 回答
0

这就是我将包含用户属性的整个对象添加到声明列表中的方式。我刚刚将带有序列化对象的名称添加到userClaims列表中。最后,您可以将 传递List<Claim>ClaimsIdentity对象。

 List<Claim> userClaims = new();
 userClaims.Add(new Claim(nameof(user), JsonConvert.SerializeObject(user)));
 var claimsIdentity = new ClaimsIdentity(userClaims)

提取令牌时,您可以执行类似的操作将其转换为对象,在我的例子中是 user 类型的对象User

var jwtToken = (JwtSecurityToken)validatedToken;
var user = JsonConvert.DeserializeObject<User>(jwtToken.Claims.First(x => x.Type == "user").Value);
于 2021-08-14T10:38:57.510 回答