我收到了要添加 jwt 令牌的声明
获取有效声明并生成 Jwt 令牌
var claims = await GetValidClaims(users);
Token = GenerateJwtToken(users, claims);
生成JwtToken方法
private string GenerateJwtToken(ApplicationUser user, List<Claim> claims)
{
var dicClaim = new Dictionary<string,object>();
...
var tokenDescriptor = new SecurityTokenDescriptor
{
Claims = dicClaim, // <<<<<<<<<< this Claims is Dictionary<string,object>
...
}
}
GetValidClaims 方法
private async Task<List<Claim>> GetValidClaims(ApplicationUser user)
{
IdentityOptions _options = new IdentityOptions();
var claims = new List<Claim>
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(_options.ClaimsIdentity.UserIdClaimType, user.Id.ToString()),
new Claim(_options.ClaimsIdentity.UserNameClaimType, user.UserName)
};
var userClaims = await _userManager.GetClaimsAsync(user);
var userRoles = await _userManager.GetRolesAsync(user);
claims.AddRange(userClaims);
foreach (var userRole in userRoles)
{
claims.Add(new Claim(ClaimTypes.Role, userRole));
var role = await _roleManager.FindByNameAsync(userRole);
if (role != null)
{
var roleClaims = await _roleManager.GetClaimsAsync(role);
foreach (Claim roleClaim in roleClaims)
{
claims.Add(roleClaim);
}
}
}
return claims;
}
在这一行:
Claims = dicClaim, // <<<<<<<<<< this Claims is Dictionary<string,object>
但是我不知道如何将List转换为Dictionary
我已经尝试过这样的事情:
claims.ToDictionary(x=>x,x=>x.Value)
claims.ToDictionary(x=>x.Value,x=>x)
图书馆
SecurityTokenDescriptor
为了创建一个字典,我们必须为其定义一个unique
Key
。假设
Type
或至少从Type
开始
Group
Type
(所需密钥)的所有索赔
1
声明,请使用
Value
作为
Key
Type_1
,
Type_2
, ...,
Type_N
Key
s
var dicClaim = claims
.GroupBy(claim => claim.Type) // Desired Key
.SelectMany(group => group
.Select((item, index) => group.Count() <= 1
? Tuple.Create(group.Key, item) // One claim in group
: Tuple.Create($"{group.Key}_{index + 1}", item) // Many claims
))
.ToDictionary(tuple => tuple.Item1, tuple => tuple.Item2);
如果遇到
repeated 声明,您只想获得 Last
一个,您可以使用以下代码来实现:
var dicClaim = claims
.GroupBy(claim => claim.Type) // Desired Key
.ToDictionary(group => group.Key, group => group.Last());
System.IdentityModel.Tokens.Jwt
的
IList<Claims>
升级到使用
Microsoft.IdentityModel.JsonWebTokens
的
Dictionary<string,object>
。 Dmitry 在 2019 年提供的答案正如他所描述的那样,但我认为这不是 JWT 的正确方法。例如,如果您有两个角色声明,使用 Dmitry 的方法将生成如下声明:
{
"role_1": "User",
"role_2": "Manager"
}
不幸的是,你在 JWT 中真正想要的是:
{
"role": [
"User",
"Manager"
]
}
更令人困惑的是,如果用户只有一个角色,JWT 不使用 JSON 数组:
{
"role": "Manager"
}
因此,考虑到这些要求,这里有一个处理这两种情况的简单扩展方法:
public static Dictionary<string, object> ToClaimsDictionary(
this IEnumerable<Claim> claims)
=> claims
.GroupBy(i => i.Type)
.ToDictionary(
i => i.Key,
i => (object)(i.Count() == 1 ? i.First().Value : i.Select(i => i.Value).ToArray()));