解析 JWT 令牌以仅在 C# 或 Blazor 中没有外部库的情况下获取有效负载内容

Posted

技术标签:

【中文标题】解析 JWT 令牌以仅在 C# 或 Blazor 中没有外部库的情况下获取有效负载内容【英文标题】:Parse JWT Token to get the payload content only without external library in C# or Blazor 【发布时间】:2020-06-09 18:38:49 【问题描述】:

我正在使用可以访问 JWT 的 Blazor 编写客户端应用程序。我想知道一种在不添加额外依赖项的情况下读取令牌有效负载内容的简单方法,因为我不需要其他信息,也不需要验证令牌。我认为解析payload内容应该足够简单,只需将其写入一个方法即可。

    JwtTokenContent ReadJwtTokenContent(string token)
    
        var content = token.Split('.')[1];

        // Exception here, it's not a valid base64 string
        var jsonPayload = Encoding.UTF8.GetString(
            Convert.FromBase64String(content));

        Console.WriteLine(jsonPayload);

        return JsonSerializer.Deserialize<JwtTokenContent>(jsonPayload);
    

如何解码有效载荷?它似乎不仅仅是一个 base64 字符串。

输入不是有效的 Base-64 字符串,因为它包含非 base-64 字符、两个以上的填充字符或填充字符中的非法字符。

这是一个示例 JWT 令牌:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJJZCI6IjUyYjg3ZTUwLTViYmMtNDE0Ny1iOTMwLWY2ZGI0ZTUyNDEwYiIsIlVzZXJuYW1lIjoiZGF0dm1Ab3V0bG9vay5jb20iLCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDMyMi8ifQ.4wKxDCwQ6onvNA_atndSitGjufR-tXutWq-tRNhqKzc P>

(内容为eyJJZCI6IjUyYjg3ZTUwLTViYmMtNDE0Ny1iOTMwLWY2ZGI0ZTUyNDEwYiIsIlVzZXJuYW1lIjoiZGF0dm1Ab3V0bG9vay5jb20iLCJpc3MiOiJodHRwczovL2xvY2FsaG9zdDo0NDMyMi8ifQ


感谢 Kalten,这是我的案例的解决方案:

    JwtTokenContent ReadJwtTokenContent(string token)
    
        var content = token.Split('.')[1];
        Console.WriteLine(content);

        var jsonPayload = Encoding.UTF8.GetString(
            this.Decode(content));
        Console.WriteLine(jsonPayload);

        return JsonSerializer.Deserialize<JwtTokenContent>(jsonPayload);
    

    byte[] Decode(string input)
    
        var output = input;
        output = output.Replace('-', '+'); // 62nd char of encoding
        output = output.Replace('_', '/'); // 63rd char of encoding
        switch (output.Length % 4) // Pad with trailing '='s
        
            case 0: break; // No pad chars in this case
            case 2: output += "=="; break; // Two pad chars
            case 3: output += "="; break; // One pad char
            default: throw new System.ArgumentOutOfRangeException("input", "Illegal base64url string!");
        
        var converted = Convert.FromBase64String(output); // Standard base64 decoder
        return converted;
    

【问题讨论】:

谢谢,刚刚更新以包含这些信息。基本上我认为证明添加依赖项的理由太简单了,尤其是我正在为 Blazor WebAssembly 编写,这是一个客户端,稍后将由客户端下载。 您需要将缺少的尾随填充添加到 base64 字符串。见Jose-jwt实现 嘿@LukeVo,可以肯定的是,您尝试解码支持 Base64Url 的有效负载,对吧?它可能是一个伪注释,但Base64Url(由JWT 使用)是对main Base64 standard : 的修改 @Kalten 谢谢,我不知道这不是标准的base64。我已经添加了解决方案,请复制并给出答案:) 这和下面的答案一样有效。哪一个更好?还是没有任何区别? 【参考方案1】:

史蒂夫·安德森试试这个

 public static IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
    
        var payload = jwt.Split('.')[1];
        var jsonBytes = ParseBase64WithoutPadding(payload);
        var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
        return keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()));
    

    private static byte[] ParseBase64WithoutPadding(string base64)
    
        switch (base64.Length % 4)
        
            case 2: base64 += "=="; break;
            case 3: base64 += "="; break;
        
        return Convert.FromBase64String(base64);
    

用法

var token = await GetTokenAsync();
        var identity = string.IsNullOrEmpty(token)
            ? new ClaimsIdentity()
            : new ClaimsIdentity(ServiceExtensions.ParseClaimsFromJwt(token), "jwt");

【讨论】:

以上是关于解析 JWT 令牌以仅在 C# 或 Blazor 中没有外部库的情况下获取有效负载内容的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Aws AppSync 将 JWT 令牌(或任何其他变量)从父解析器传递给子解析器

仅在 JWT 令牌中而不是在 OAuth2 令牌中添加附加信息

使用 Emgu CV C# 创建轮廓蒙版以仅在原始图像上显示 ROI

C# 使用来自授权端点 (crv, x, y) 的值验证 JWT 令牌

如何在没有 Microsoft 身份的情况下对 blazor 服务器进行 jwt 身份验证?

WiX:如何打包 exe 或 dll 以仅在安装期间使用