IdentityServer4客户端JWT解密实现(基于.net4.0)

情景:公司项目基于.net4.0,web客户端实现单点登录需要自己解密id_token,对于jwt解密,.net提供了IdentityModel类库,但是4.0中该类库不可用,所以自己实现了解密方法..

使用了类库:https://github.com/jwt-dotnet/jwt

下面直接贴代码,直接调用DecodeJWT方法就行,参数为id_token,key默认为空字符串"",


public static IDictionary<string, object> DecodeJWT(string jwttoken,string key)
        {

            //从/.well-known/openid-configuration路径获取jwks_uri
            var webClient = new WebClient();

            var endpoint = "http://localhost:5000/.well-known/openid-configuration";

            var json = webClient.DownloadString(endpoint);

            JObject metadata = JsonConvert.DeserializeObject<JObject>(json);

            var jwksUri = metadata["jwks_uri"].ToString();

            //从jwks_uri获取keys
            json = webClient.DownloadString(jwksUri);

            var keys = JsonConvert.DeserializeObject<CustomJWKs>(json);

            //从jwt获取头部kid,并从keys中找到匹配kid的key
            string[] tokenParts = jwttoken.Split(‘.‘);
            byte[] bytes = FromBase64Url(tokenParts[0]);
            string head= Encoding.UTF8.GetString(bytes);
            string kid = JsonConvert.DeserializeObject<JObject>(head)["kid"].ToString();

            var defaultkey=keys.keys.Where(t => t.kid == kid).FirstOrDefault();

            if(defaultkey==null)
            {
                throw new Exception("未找到匹配的kid");
            }

            //jwt解密
            return RS256Decode(jwttoken, key, defaultkey.e, defaultkey.n);
        }

         public static IDictionary<string, object> RS256Decode(string token, string secret, string exponent,string modulus)
        {
            try
            {
                IJsonSerializer serializer = new JsonNetSerializer();
                IDateTimeProvider provider = new UtcDateTimeProvider();
                IJwtValidator validator = new JwtValidator(serializer, provider);
                IBase64UrlEncoder urlEncoder = new JwtBase64UrlEncoder();
                RSAlgorithmFactory rS256Algorithm = new RSAlgorithmFactory(() =>
                {
                    RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                    rsa.ImportParameters(
                      new RSAParameters()
                      {
                          Modulus = FromBase64Url(modulus),
                          Exponent = FromBase64Url(exponent)
                      });

                    byte[] rsaBytes = rsa.ExportCspBlob(true);

                    X509Certificate2 cert = new X509Certificate2(rsaBytes);
                    return cert;
                });

                IJwtDecoder decoder = new JwtDecoder(serializer, validator, urlEncoder, rS256Algorithm);
                var json = decoder.DecodeToObject(token, secret, verify: false);
                return json;
            }
            catch (TokenExpiredException)
            {
                throw new Exception("token已过期");
                //Console.WriteLine("Token has expired");
                //return null;
            }
            catch (SignatureVerificationException)
            {
                throw new Exception("token验证失败");
                //Console.WriteLine("Token has invalid signature");
                //return null;
            }
        }

        public static byte[] FromBase64Url(string base64Url)
        {
            string padded = base64Url.Length % 4 == 0
                ? base64Url : base64Url + "====".Substring(base64Url.Length % 4);
            string base64 = padded.Replace("_", "/")
                                  .Replace("-", "+");
            return Convert.FromBase64String(base64);
        }

原文地址:https://www.cnblogs.com/ldybyz/p/9688088.html

时间: 2024-10-12 20:43:55

IdentityServer4客户端JWT解密实现(基于.net4.0)的相关文章

基于.net4.0或者更低版本的INotifyPropertyChanged接口测试

基于OAuth2.0协议 第三方登录与数据同步验证设计

前段时间,公司跟别的公司签订合作伙伴,搞了一个第三方登录与数据共享同步,是基于OAuth2.0协议,现在空闲了,做一下笔记. 到github下载一个OAuth2.0的PHP类库(当然,你也可以自己写一个^-^,但个人觉得没必要造轮子),有写好Mysql与Mongodb的Demo,参考一下,然后嵌套自己的业务代码,下面是客户端与服务端的交互流程: +-----------+ +-----------+| | 带client_id的URL请求获取code | || | ---------------

WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4)

写在最前面:转载请注明出处 目录置顶: 关于项目--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(1) 架构搭建--------------------基于DDD领域驱动设计的WCF+EF+WPF分层框架(2) WCF服务端具体实现---------基于DDD领域驱动设计的WCF+EF+WPF分层框架(3) WCF客户端配置以及代理-----基于DDD领域驱动设计的WCF+EF+WPF分层框架(4) Domain具体实现------------基于DD

类型:.net;问题:iis注册;结果:.net4.0注册到IIS ,重新注册IIS ,iis注册

.net4.0注册到IIS ,重新注册IIS ,iis注册 IIS和.netfw4.0安装顺序是从前到后,如果不小心颠倒了,无所谓. 打开程序-运行-cmd:输入一下命令重新注册IIS C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -i 一.找到C:\WINNT\MICROSOFT.NET\FRAMEWORK\V版本号\ASPNET_REGIIS.EXE 直接双击运行 即可,好像通过DOS命令不行. 二.开始- 程

.Net4.0 任务(Task)[转]

.Net4.0 任务(Task) 任务(Task)是一个管理并行工作单元的轻量级对象.它通过使用CLR的线程池来避免启动专用线程,可以更有效率的利用线程池.System.Threading.Tasks 命名空间下任务相关类一览: 类 作用 Task 管理工作单元 Task<TResult> 管理带返回值的工作单元 TaskFactory 创建任务 TaskFactory<TResult> 创建任务或者有相同返回值的延续任务 TaskScheduler 管理任务调度 TaskComp

.Net4.0 任务(Task)

.Net4.0 任务(Task),.net4.0任务task 任务(Task)是一个管理并行工作单元的轻量级对象.它通过使用CLR的线程池来避免启动专用线程,可以更有效率的利用线程池.System.Threading.Tasks 命名空间下任务相关类一览: 类 作用 Task 管理工作单元 Task<TResult> 管理带返回值的工作单元 TaskFactory 创建任务 TaskFactory<TResult> 创建任务或者有相同返回值的延续任务 TaskScheduler 管

.NET4.0多线程编程---Cooperative Cancellation

在多线程编程中线程池是不得不提的,在.net4.0之前一般对于线程池的说法是,把需要的线程交给线程池,我们自己将更多的关注点放在业务上,个人认为这既是线程池的优点也是缺点---加入线程池之后人为无法控制,也没有内在的方法告知线程的执行结果. 今天早晨拜读了Jeffrey的著作26th章.根据自己的理解今天主要学习“如何取消线程池中的线程”. 首先介绍System.Thread命名空间下面的两个类: CancellationToken ,其实这是一个结构,它主要传播有关应取消操作的通知. Canc

ASP.NET4.0新特性

原文:ASP.NET4.0新特性 在以前试用VS2010的时候已经关注到它在Web开发支持上的一些变化了,为此我还专门做了一个ppt,当初是计划在4月12日那天讲的,结果因为莫名其妙的原因导致没有语音以致放弃在LiveMeeting上的这次讲课,也导致了本篇的产生. 新增了项目模板 在创建Web项目时可以看到增加了更多的Web项目模板在VS2008中对应的情况如下: 在新模板中有如下改进:基础MemberShip功能.在大多数网站和应用程序中需要进行认证,因此在新模板中增加了认证功能使得用户能在

红米3(ido)基于6.0.1适配第三方中文jirecovery/TWRP 3.0.2/刷遍所有ROM/官方不卡屏

TWRP3.0.2更新简介: TWRP是TeamWin团队https://github.com/TeamWin/Team-Win-Recovery-Project的开源项目,也是Omnirom系统默认的android_bootable_recovery. 红米3-TWRP-21060823更新日志: 1.基于Aink1199的20160805-cm13最新6.01内核制作. 2.基于omnirom-android-6.0适配. 3.加入禁止恢复官方recovery选项(刷完机重启时会提示). 4