JWT 如何添加自定义声明和解码声明

Posted

技术标签:

【中文标题】JWT 如何添加自定义声明和解码声明【英文标题】:JWT How to add custom claims and decode claims 【发布时间】:2019-02-26 23:44:27 【问题描述】:

我正在尝试检索我在创建令牌时所做的一些自定义声明。但是,我不确定我应该写什么来检索这些声明。

这是我的令牌创建函数

public String createToken(AuthenticationDTO Input)

    //Set issued at date
    DateTime issuedAt = DateTime.UtcNow;
    //set the time when it expires
    DateTime expires = DateTime.UtcNow.AddDays(7);

    //http://***.com/questions/18223868/how-to-encrypt-jwt-security-token
    var tokenHandler = new JwtSecurityTokenHandler();

    //create a identity and add claims to the user which we want to log in
    ClaimsIdentity claimsIdentity = new ClaimsIdentity(new[]
    
        new Claim("UserName", Input.UserName),
        new Claim("Email",Input.Email),
        new Claim("PhoneNumber",Input.PhoneNumber),
        new Claim("FirstName",Input.FirstName),
        new Claim("LastName",Input.LastName),
        new Claim("Id",Input.Id)
    );

    const string sec = HostConfig.SecurityKey;
    var now = DateTime.UtcNow;
    var securityKey = new SymmetricSecurityKey(System.Text.Encoding.Default.GetBytes(sec));
    var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);


    //create the jwt
    var token =(JwtSecurityToken)
            tokenHandler.CreateJwtSecurityToken(issuer: HostConfig.Issuer, audience: HostConfig.Audience,
                subject: claimsIdentity, notBefore: issuedAt, expires: expires, signingCredentials: signingCredentials);
    var tokenString = tokenHandler.WriteToken(token);

    return tokenString;

我决定命名我自己的声明,而不是使用提供的标准声明。但是,我不知道如何检索它们。这是我目前拥有的:

public AuthenticationDTO DecodeToken(String Input)

    var key = Encoding.ASCII.GetBytes(HostConfig.SecurityKey);
    var handler = new JwtSecurityTokenHandler();
    var tokenSecure = handler.ReadToken(Input) as SecurityToken;
    var validations = new TokenValidationParameters
    
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false,
        ValidateAudience = false
    ;
    var claims = handler.ValidateToken(Input, validations, out tokenSecure);
    return null;

编辑:

我注意到我的索赔是这样来的

如何提取它们?

EDIT2:

添加了 AuthentcationDTO

public class AuthenticationDTO

    public String Id  get; set; 
    public String UserName  get; set; 
    public String Email  get; set; 
    public String FirstName  get; set; 
    public String LastName  get; set; 
    public String PhoneNumber  get; set; 

【问题讨论】:

使用 ClaimsPrincipal 你也可以提供AuthenticationDTO 类吗? 添加了 AuthenticationDTO 【参考方案1】:

如果您想获得声明,即preferred_username,您可以从 ClaimsPrincipal 获得。

var user = User as ClaimsPrincipal;
string username = user.Claims.Where(c => c.Type == "preferred_username")
    .Select(x => x.Value).FirstOrDefault();

User 将来自Claims。对于那个写

using System.Security.Claims;

似乎User 并非在所有版本中都可用。获得索赔的另一种方法是类似的。

var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
var email = prinicpal.Claims.Where(c => c.Type == ClaimTypes.Email)
    .Select(c => c.Value).SingleOrDefault();

AuthenticationDTO分配所有值。

public AuthenticationDTO DecodeToken(String Input)

    var key = Encoding.ASCII.GetBytes(HostConfig.SecurityKey);
    var handler = new JwtSecurityTokenHandler();
    var tokenSecure = handler.ReadToken(Input) as SecurityToken;
    var validations = new TokenValidationParameters
    
        ValidateIssuerSigningKey = true,
        IssuerSigningKey = new SymmetricSecurityKey(key),
        ValidateIssuer = false,
        ValidateAudience = false
    ;
    var claims = handler.ValidateToken(Input, validations, out tokenSecure);
    var prinicpal = (ClaimsPrincipal)Thread.CurrentPrincipal;
    if (principal is ClaimsPrincipal claims)
    
         return new ApplicationDTO
             
                 Id = claims.Claims.FirstOrDefault(x => x.Type == "sub")?.Value ?? "",
                 UserName = claims.Claims.FirstOrDefault(x => x.Type == "preferred_username")?.Value ?? "",
                 Email = claims.Claims.FirstOrDefault(x => x.Type == "email")?.Value ?? ""
             ;
    
    return null;

【讨论】:

抱歉,您是从哪里获得 User as ClaimsPrincipal 的?我无法让用户出现 User 来自使用System.Security.Claims 由于某种原因我在 System.Security.Claims 中没有用户 如果您查看我在问题中添加的图像,看来我必须循环遍历并将它们拆分为键值项? 您可以使用 linq 获取所有值。您可以使用principal 接收电子邮件吗?

以上是关于JWT 如何添加自定义声明和解码声明的主要内容,如果未能解决你的问题,请参考以下文章

AWS Cognito:将自定义声明/属性添加到 JWT 访问令牌

向 ID 令牌 OpenID 添加自定义声明

ASP.NET Core 2.1 Jwt 设置自定义声明

如何根据用户输入在 Jwt Token 上添加自定义声明?

如何使用 JJWT 从有效负载中获取自定义字段

无法在 Tymon JWT 中添加自定义声明