在C#中将JWT令牌单个声明属性添加为数组元素

5
我希望在C#中将一个角色添加为JWT令牌的数组元素。
{
   "roles": ["Administrator"]
}

目前,我使用这种代码来生成JWT令牌声明。但它无法帮助我创建数组类型的声明。

string PrivateKey = "string private here";
List<Claim> claims = new List<Claim>();
claims.Add(new Claim("roles", "[Administrator]"));
string tokenString = CreateToken(claims, PrivateKey);

public string CreateToken(List<Claim> claims, string privateRsaKey)
        {
.........................................................
                JwtSecurityToken token = new JwtSecurityToken(
                        Issuer,
                        Audience,
                        claims,
                        now,
                        Expiration,
                        null);

                string payload = token.Payload.SerializeToJson();
                return Jose.JWT.Encode(payload, rsa, Jose.JwsAlgorithm.RS256);

}

实际上,我只想添加一个数组元素。但我不能像这样做,因为它会添加多个数组元素。

List<Claim> claims = new List<Claim>();
claims.Add(new Claim("roles", "[Administrator]"));
claims.Add(new Claim("roles", "[Administrator]"));

我该如何做到这一点?


可能是Add a claim to JWT as an array?的重复问题。 - d00lar
我想添加一个数组元素。(例如:{ "roles": "["Administrator"]" })因此,我无法重复添加一个声明来创建一个数组。 - user3732708
你可以序列化例如 new Claim("APIs", JsonConvert.SerializeObject(cos)));。 - d00lar
@d00lar 当序列化ID时,每个属性上都有键和值,例如 "user": { "userKey": "batman", "username": "bwayne", "displayName": "Bruce Wayne" }。我不想要一个键,我只想要一个值作为数组元素。 - user3732708
1
或者在字符串 'yourway' 中准备您的数组 - 多次附加以获得 "roles","管理员、用户、已验证",然后在访问时通过 ',' 字符拆分为数组即可;P 肮脏但可行。 - d00lar
显示剩余2条评论
4个回答

4

最终,在花费数小时的时间后,我找到了答案,我必须改变生成声明的方式并对jwt令牌进行编码。

List < string > roleOptions = new List < string > () {
 "Administrator"
};
var payload = new JwtPayload {
 {
  "roles",
  roleOptions
 }
};

    string key = "eyJjb21wYW5pZXMiOlt7IklkIjoxLCJDb2RlIjoiQzAxIiwiTmFtZSI6IkNvbXBhbnkgSSIsIkJyYW5jaGVzIjpudWxsLCJVc2VycyI6W3siSWQiOjEsIk5hbWUiOiJV";
    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
    var header = new JwtHeader(credentials);
    var secToken = new JwtSecurityToken(header, payload);
    var handler = new JwtSecurityTokenHandler();
    var tokenString1 = handler.WriteToken(secToken);
    _logger.Info(secToken.ToString());
    _logger.Info(tokenString1);

0

这是我的实现

包含

  • 令牌过期
  • 角色数组为List<string>

https://github.com/scholtz/covid-sk-api/blob/main/CovidMassTesting/Model/Token.cs

请注意,usr.Roles 必须是 List<string> 而不是 string[]
        /// <summary>
        /// Method creates jwt token
        /// </summary>
        /// <param name="usr">User object</param>
        /// <param name="configuration">APP Configuran</param>
        /// <returns></returns>
        public static string CreateToken(User usr, IConfiguration configuration)
        {
            if (usr is null)
            {
                throw new ArgumentNullException(nameof(usr));
            }

            if (configuration is null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            var key = Encoding.ASCII.GetBytes(configuration["JWTTokenSecret"]);

            var payload = new JwtPayload {
                  {
                    Token.Claims.Email,
                     usr.Email
                  },{
                    Token.Claims.Name,
                     usr.Name
                  },
                  {
                    Token.Claims.Role,
                     usr.Roles
                  },
                  {
                    "nbf",
                     DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeSeconds()
                  },
                  {
                    "iat",
                     DateTimeOffset.UtcNow.AddSeconds(-1).ToUnixTimeSeconds()
                  },
                  {
                    "exp",
                     DateTimeOffset.UtcNow.AddDays(1).ToUnixTimeSeconds()
                  },
            };

            var credentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature);

            var header = new JwtHeader(credentials);
            var secToken = new JwtSecurityToken(header, payload);
            var handler = new JwtSecurityTokenHandler();
            return handler.WriteToken(secToken);
        }

0

这部分真的帮了我很多:

如果要将数组作为键添加,我们必须将其转换为列表,然后将其添加到jwt负载中。

    List < string > roleOptions = new List < string > () { 
      "Administrator"
    };
    var payload = new JwtPayload {
      {
        "roles",
         roleOptions
      }
    };

0
经过多次尝试和整个周末的努力,我终于成功解决了转换单例数组的问题。
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Newtonsoft.Json;

IList<string> roleList = new List<string>();
roleList.Add("Administrator");

string rolesJson = JsonConvert.SerializeObject(roleList);

claims.Add(new Claim("roles", rolesJson, JsonClaimValueTypes.JsonArray));

var jwt = new JwtSecurityToken(
                issuer: ...,
                audience: ...,
                claims: claims ..);

将值数组序列化为JSON,并将声明添加为JSON值类型。希望这可以帮助那些与此类问题挣扎的人。

干杯!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接