【问题标题】:How to decode JWT Token?如何解码 JWT 令牌?
【发布时间】:2016-11-15 08:33:26
【问题描述】:

我不明白这个库是如何工作的。你能帮帮我吗?

这是我的简单代码:

public void TestJwtSecurityTokenHandler()
    {
        var stream =
            "eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJJU1MiLCJzY29wZSI6Imh0dHBzOi8vbGFyaW0uZG5zY2UuZG91YW5lL2NpZWxzZXJ2aWNlL3dzIiwiYXVkIjoiaHR0cHM6Ly9kb3VhbmUuZmluYW5jZXMuZ291di5mci9vYXV0aDIvdjEiLCJpYXQiOiJcL0RhdGUoMTQ2ODM2MjU5Mzc4NClcLyJ9";
        var handler = new JwtSecurityTokenHandler();

        var jsonToken = handler.ReadToken(stream);
    }

这是错误:

字符串需要采用紧凑的 JSON 格式,格式为:Base64UrlEncodedHeader.Base64UrlEndcodedPayload.OPTIONAL,Base64UrlEncodedSignature'。

如果你复制jwt.io website中的流,它工作正常:)

【问题讨论】:

标签: c# .net jwt


【解决方案1】:

我找到了解决方案,我只是忘了投射结果:

var stream = "[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jsonToken = handler.ReadToken(stream);
var tokenS = jsonToken as JwtSecurityToken;

或者,没有演员表:

var token = "[encoded jwt]";  
var handler = new JwtSecurityTokenHandler();
var jwtSecurityToken = handler.ReadJwtToken(token);

我可以通过以下方式获得索赔:

var jti = tokenS.Claims.First(claim => claim.Type == "jti").Value;

【讨论】:

  • 你也可以这样做:handler.ReadJwtToken(tokenJwtReponse.access_token);
  • 很抱歉,这应该很明显,但tokenJwtReponse.access_token 来自哪里?
  • tokenJwtReponse.access_token 来自哪里?
  • 正如其他人已经质疑的那样:“tokenJwtReponse.access_token”来自哪里?答案中没有对它的定义或声明,这使得答案对我们许多人来说毫无用处和毫无意义。
  • 我需要包含以下 NuGet 包才能在我的 Azure 函数中使用它:System.IdentityModel.Tokens.Jwt
【解决方案2】:

new JwtSecurityTokenHandler().ReadToken("") 将返回 SecurityToken

new JwtSecurityTokenHandler().ReadJwtToken("") 将返回 JwtSecurityToken

如果您只是更改使用的方法,则可以避免上述答案中的演员表

【讨论】:

    【解决方案3】:

    使用 .net core jwt 包,声明可用:

    [Route("api/[controller]")]
    [ApiController]
    [Authorize(Policy = "Bearer")]
    public class AbstractController: ControllerBase
    {
        protected string UserId()
        {
            var principal = HttpContext.User;
            if (principal?.Claims != null)
            {
                foreach (var claim in principal.Claims)
                {
                   log.Debug($"CLAIM TYPE: {claim.Type}; CLAIM VALUE: {claim.Value}");
                }
    
            }
            return principal?.Claims?.SingleOrDefault(p => p.Type == "username")?.Value;
        }
    }
    

    【讨论】:

    • 这仅在使用基于 ASP.NET Core 的中间件管道时才可行,OP 专门要求处理程序在实现 System.IdentityModel.Tokens.Jwt 中的实现,它适合更广泛的用例集。
    【解决方案4】:

    您需要用于生成加密令牌的秘密字符串。 这段代码对我有用:

    protected string GetName(string token)
        {
            string secret = "this is a string used for encrypt and decrypt token"; 
            var key = Encoding.ASCII.GetBytes(secret);
            var handler = new JwtSecurityTokenHandler();
            var validations = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(key),
                ValidateIssuer = false,
                ValidateAudience = false
            };
            var claims = handler.ValidateToken(token, validations, out var tokenSecure);
            return claims.Identity.Name;
        }
    

    【讨论】:

    • 当您稍后将其重新分配为out 参数时,为什么要调用handler.ReadToken(token) as SecurityToken?是否有可能ValidateToken 失败并保留原始值?
    • 正确的 krillgar 不需要转换为 SecurityToken
    • ValidateToken 检查过期时间吗?还是我需要在解码后验证自己?
    • @computrius ValidateToken 采用TokenValidationParameters,它是在调用之前的行上构造的,正如答案中清楚地看到的那样。该对象将告诉验证器要检查的内容。
    【解决方案5】:

    cooxkie 答案和dpix 答案上进行扩展,当您读取 jwt 令牌(例如从 AD FS 接收到的 access_token)时,您可以将 jwt 令牌中的声明与“context.xml”中的声明合并。 AuthenticationTicket.Identity”,可能与 jwt 令牌的声明集不同。

    为了说明,在使用 OpenID Connect 的身份验证代码流中,用户通过身份验证后,您可以处理事件SecurityTokenValidated,它为您提供身份验证上下文,然后您可以使用它来读取 access_token 作为 jwt 令牌,然后您可以将 access_token 中的令牌与作为用户身份的一部分接收的标准声明列表“合并”:

        private Task OnSecurityTokenValidated(SecurityTokenValidatedNotification<OpenIdConnectMessage,OpenIdConnectAuthenticationOptions> context)
        {
            //get the current user identity
            ClaimsIdentity claimsIdentity = (ClaimsIdentity)context.AuthenticationTicket.Identity;
    
            /*read access token from the current context*/
            string access_token = context.ProtocolMessage.AccessToken;
    
            JwtSecurityTokenHandler hand = new JwtSecurityTokenHandler();
            //read the token as recommended by Coxkie and dpix
            var tokenS = hand.ReadJwtToken(access_token);
            //here, you read the claims from the access token which might have 
            //additional claims needed by your application
            foreach (var claim in tokenS.Claims)
            {
                if (!claimsIdentity.HasClaim(claim.Type, claim.Value))
                    claimsIdentity.AddClaim(claim);
            }
    
            return Task.FromResult(0);
        }
    

    【讨论】:

      【解决方案6】:
        var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
        var claims = new[]
        {
            new Claim(JwtRegisteredClaimNames.Email, model.UserName),
            new Claim(JwtRegisteredClaimNames.NameId, model.Id.ToString()),
        };
        var token = new JwtSecurityToken(_config["Jwt:Issuer"],
            _config["Jwt:Issuer"],
            claims,
            expires: DateTime.Now.AddMinutes(30),
            signingCredentials: creds);
      

      然后提取内容

       var handler = new JwtSecurityTokenHandler();
       string authHeader = Request.Headers["Authorization"];
       authHeader = authHeader.Replace("Bearer ", "");
       var jsonToken = handler.ReadToken(authHeader);
       var tokenS = handler.ReadToken(authHeader) as JwtSecurityToken;
       var id = tokenS.Claims.First(claim => claim.Type == "nameid").Value;
      

      【讨论】:

        【解决方案7】:

        我写了这个解决方案,它对我有用

            protected Dictionary<string, string> GetTokenInfo(string token)
            {
                var TokenInfo = new Dictionary<string, string>();
        
                var handler = new JwtSecurityTokenHandler();
                var jwtSecurityToken = handler.ReadJwtToken(token);
                var claims = jwtSecurityToken.Claims.ToList();
        
                foreach (var claim in claims)
                {
                    TokenInfo.Add(claim.Type, claim.Value);
                }
        
                return TokenInfo;
            }
        

        【讨论】:

          猜你喜欢
          • 2021-12-30
          • 2018-10-05
          • 2020-02-02
          • 2019-05-19
          • 2017-04-16
          • 2016-10-08
          • 2021-03-24
          • 2021-09-10
          相关资源
          最近更新 更多