是否有 C# 中的 JSON Web Token (JWT) 示例?

2023-12-01

我觉得我在这里服用了疯狂的药。通常,对于任何给定的任务,网络上总会有一百万个库和示例。我正在尝试使用 JSON Web Tokens (JWT) 来实现 Google“服务帐户”的身份验证,如下所述here.

但是,只有 PHP、Python 和 Java 版本的客户端库。即使在 Google 认证之外搜索 JWT 示例,也只有关于 JWT 概念的蟋蟀和草稿。这真的那么新并且可能是谷歌专有系统吗?

我能解释的最接近的 java 示例看起来非常密集和令人生畏。 C# 中肯定有一些我至少可以开始的东西。任何对此的帮助都会很棒!


我找到了 Json Web Token 的基本实现,并用 Google 风格对其进行了扩展。我还没有完全解决,但已经97%了。这个项目失去了动力,所以希望这能帮助其他人取得良好的开端:

笔记: 我对基本实现所做的更改(不记得在哪里找到它)是:

  1. 更改HS256 -> RS256
  2. 交换了标头中的 JWT 和 alg 顺序。不确定谁弄错了,谷歌还是规范,但谷歌根据他们的文档采用了下面的方式。
public enum JwtHashAlgorithm
{
    RS256,
    HS384,
    HS512
}
    
public class JsonWebToken
{
    private static Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>> HashAlgorithms;

    static JsonWebToken()
    {
        HashAlgorithms = new Dictionary<JwtHashAlgorithm, Func<byte[], byte[], byte[]>>
            {
                { JwtHashAlgorithm.RS256, (key, value) => { using (var sha = new HMACSHA256(key)) { return sha.ComputeHash(value); } } },
                { JwtHashAlgorithm.HS384, (key, value) => { using (var sha = new HMACSHA384(key)) { return sha.ComputeHash(value); } } },
                { JwtHashAlgorithm.HS512, (key, value) => { using (var sha = new HMACSHA512(key)) { return sha.ComputeHash(value); } } }
            };
    }

    public static string Encode(object payload, string key, JwtHashAlgorithm algorithm)
    {
        return Encode(payload, Encoding.UTF8.GetBytes(key), algorithm);
    }

    public static string Encode(object payload, byte[] keyBytes, JwtHashAlgorithm algorithm)
    {
        var segments = new List<string>();
        var header = new { alg = algorithm.ToString(), typ = "JWT" };

        byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(header, Formatting.None));
        byte[] payloadBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));
        //byte[] payloadBytes = Encoding.UTF8.GetBytes(@"{"iss":"761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com","scope":"https://www.googleapis.com/auth/prediction","aud":"https://accounts.google.com/o/oauth2/token","exp":1328554385,"iat":1328550785}");

        segments.Add(Base64UrlEncode(headerBytes));
        segments.Add(Base64UrlEncode(payloadBytes));

        var stringToSign = string.Join(".", segments.ToArray());

        var bytesToSign = Encoding.UTF8.GetBytes(stringToSign);

        byte[] signature = HashAlgorithms[algorithm](keyBytes, bytesToSign);
        segments.Add(Base64UrlEncode(signature));

        return string.Join(".", segments.ToArray());
    }

    public static string Decode(string token, string key)
    {
        return Decode(token, key, true);
    }

    public static string Decode(string token, string key, bool verify)
    {
        var parts = token.Split('.');
        var header = parts[0];
        var payload = parts[1];
        byte[] crypto = Base64UrlDecode(parts[2]);

        var headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
        var headerData = JObject.Parse(headerJson);
        var payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
        var payloadData = JObject.Parse(payloadJson);

        if (verify)
        {
            var bytesToSign = Encoding.UTF8.GetBytes(string.Concat(header, ".", payload));
            var keyBytes = Encoding.UTF8.GetBytes(key);
            var algorithm = (string)headerData["alg"];

            var signature = HashAlgorithms[GetHashAlgorithm(algorithm)](keyBytes, bytesToSign);
            var decodedCrypto = Convert.ToBase64String(crypto);
            var decodedSignature = Convert.ToBase64String(signature);

            if (decodedCrypto != decodedSignature)
            {
                throw new ApplicationException(string.Format("Invalid signature. Expected {0} got {1}", decodedCrypto, decodedSignature));
            }
        }

        return payloadData.ToString();
    }

    private static JwtHashAlgorithm GetHashAlgorithm(string algorithm)
    {
        switch (algorithm)
        {
            case "RS256": return JwtHashAlgorithm.RS256;
            case "HS384": return JwtHashAlgorithm.HS384;
            case "HS512": return JwtHashAlgorithm.HS512;
            default: throw new InvalidOperationException("Algorithm not supported.");
        }
    }

    // from JWT spec
    private static string Base64UrlEncode(byte[] input)
    {
        var output = Convert.ToBase64String(input);
        output = output.Split('=')[0]; // Remove any trailing '='s
        output = output.Replace('+', '-'); // 62nd char of encoding
        output = output.Replace('/', '_'); // 63rd char of encoding
        return output;
    }

    // from JWT spec
    private static byte[] Base64UrlDecode(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.Exception("Illegal base64url string!");
        }
        var converted = Convert.FromBase64String(output); // Standard base64 decoder
        return converted;
    }
}

然后是我的谷歌特定 JWT 类:

public class GoogleJsonWebToken
{
    public static string Encode(string email, string certificateFilePath)
    {
        var utc0 = new DateTime(1970,1,1,0,0,0,0, DateTimeKind.Utc);
        var issueTime = DateTime.Now;

        var iat = (int)issueTime.Subtract(utc0).TotalSeconds;
        var exp = (int)issueTime.AddMinutes(55).Subtract(utc0).TotalSeconds; // Expiration time is up to 1 hour, but lets play on safe side

        var payload = new
        {
            iss = email,
            scope = "https://www.googleapis.com/auth/gan.readonly",
            aud = "https://accounts.google.com/o/oauth2/token",
            exp = exp,
            iat = iat
        };

        var certificate = new X509Certificate2(certificateFilePath, "notasecret");

        var privateKey = certificate.Export(X509ContentType.Cert);

        return JsonWebToken.Encode(payload, privateKey, JwtHashAlgorithm.RS256);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否有 C# 中的 JSON Web Token (JWT) 示例? 的相关文章

随机推荐

  • 未为参数指定实参

    使用 VB net 和 WPF 我已经转换了可用的代码使用装饰器覆盖 WPF 中的控件从 C 到 VB Net 原始 C 代码
  • Java中如何按两个字段排序?

    我有对象数组person int age String name 如何按名称字母顺序排序此数组 然后按年龄排序 您会为此使用哪种算法 您可以使用Collections sort如下 private static void order Lis
  • 使用 GSON 解析嵌套 JSON 数据

    我正在尝试使用 Java 中的 gson 解析一些 JSON 数据 其结构如下 但通过查看在线示例 我找不到任何可以完成这项工作的东西 有人可以帮忙吗 data id stuff values 123 456 123
  • 在 Salesforce iOS SDK 中查询用户名

    我有一个使用最新 Salesforce iOS SDK 的 iOS 应用程序 它使用 Salesforce 站点上的 oAuth2 0 通过 Web 视图对用户进行身份验证 因此我不会在应用程序中捕获用户名 有没有办法可以使用 API 或会
  • Swift:如果计时器从函数启动,如何使计时器无效?

    我有一个timer函数中的变量如下所示 timer NSTimer func whatever timer NSTimer scheduledTimerWithTimeInterval 1 target self selector time
  • 清除应用程序数据不会清除 GCM 令牌或 GCM 订阅主题

    我已经订阅了 GCM 的主题 当我通过 Android 设置删除所有应用程序数据时 GCM 令牌是相同的 并且有关主题的 GCM 通知仍然可用 因此我收到了我不想收到的通知 我的问题是 如何获取 GCM 订阅的所有主题的列表 如何在不知道主
  • 使用 Javascript/Jquery 上下移动节点 Div

    我想知道 Javascript 中是否有一种方法可以在没有 id 的情况下上下移动节点 div 元素 当选择该项目并右键单击时 将出现 上移 和 下移 选项 现在在 上移 上单击它应该在 div 中上移 例如 div div 1 div d
  • std::vector 实现是否使用内部数组或链表或其他?

    有人告诉我 std vector 在内部实现上有一个 C 风格的数组 但这不会否定动态容器的全部目的吗 那么在向量中插入一个值是 O n 操作吗 还是像链表那样 O 1 来自 C 11 标准 在 序列容器 库部分 强调我的 23 3 6 1
  • 如何计算进程id的执行指令数,包括所有未来的子线程

    前段时间 我问了以下问题 如何统计进程id 包括子进程 的执行指令数 M Iduoad 提供了一个解决方案pgrep捕获所有子 PID 并将其与 perf stat 中的 p 一起使用 效果很好 然而 我遇到的一个问题是多线程应用程序以及当
  • 在 ASP.NET 中管理实体框架 ObjectContext

    我正在将实体框架用于 ASP NET Web 表单应用程序 我想知道应该如何处理ObjectContext这是一生 例如 我有一个InviteService管理邀请的类 例如创建和接受邀请 该类本身位于 Web 项目的另一个项目 命名空间中
  • 在 Fedora 容器中,systemctl 给出 Failed to get D-Bus connection

    当我在 Fedora 容器中使用 systemctl 时 我得到 无法获得 D Bus 连接 未知错误 1 有人知道如何解决这个问题吗 或者说systemctl不能在docker容器中使用吗 The systemctl命令与systemd通
  • 根据 Google 表格中单列中的重复项删除行

    我有与此类似的电子表格 我想根据第一列数据删除行的所有重复项 因此 在此屏幕截图行中 将保留第 1 行和第 2 行 并删除第 2 行 任何帮助将不胜感激 附 在我的例子中 列从 A 到 AU 行从 2 到 9500 谢谢 Maya s an
  • 如何在同一个循环中同时循环所有 Firebase 子项?

    我在 firebase 中有三个节点 我想使用相同的循环来循环它们 我成功地能够使用以下代码循环遍历单个节点 cookie databaseRef child cookies observeSingleEvent of value with
  • 从 Java 到 PHP 重新创建 PDF 文件

    我有一个 Java 中的 WebService 使用 Apache Axis 它获取文档的 id 并调用 JasperReports 来创建 PDF 文件 之前在 java 应用程序中创建的报告 服务器端 以创建我正在使用的方法的报告 Ja
  • 使用 Javascript 删除从不同页面呈现的整个表格

    我有一张像这样的桌子 table class toc border 1 table 在许多页面中 所有这些页面都呈现在单个页面中 当我应用 Javascript 来删除加载时使用的内容时 仅删除一张表 其他表不会被删除 我正在尝试使用 Ja
  • Azure AD登录后如何重定向到特定页面?

    我正在将 Azure AD 登录集成到我的应用程序中 我想在成功登录天蓝色广告后重定向到特定操作 我的 Startup Auth cs 文件中有以下代码 但它没有重定向到redirecturi 任何人都可以建议我如何在成功登录后重定向到自定
  • Python Tkinter Treeview 添加图像作为列值

    我试图将图像添加到树视图上每一行的第一列 但无论我做什么 最终总是显示对象 pyimage1 的名称而不是实际图像 正如这张图片所示 我正在使用的代码是这样的 from tkinter import PhotoImage self img
  • 如何使用 jQuery 在 30 分钟内使 cookie 过期?

    如何让 Cookie 在 30 分钟内过期 我正在使用 jQuery cookie 我能够做这样的事情 cookie example foo expires 1 这是 1 天的时间 但是我们如何将到期时间设置为 30 分钟 30分钟是30
  • 在 SQL SERVER 2008 中从字符串转换日期和/或时间时转换失败

    我有以下 SQL UPDATE student queues SET Deleted 0 last accessed by raja last accessed on CONVERT VARCHAR 24 23 07 2014 09 37
  • 是否有 C# 中的 JSON Web Token (JWT) 示例?

    我觉得我在这里服用了疯狂的药 通常 对于任何给定的任务 网络上总会有一百万个库和示例 我正在尝试使用 JSON Web Tokens JWT 来实现 Google 服务帐户 的身份验证 如下所述here 但是 只有 PHP Python 和