视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
基于.net4.0实现IdentityServer4客户端JWT解密
2020-11-27 22:34:49 责编:小采
文档


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

使用了类库:链接地址

下面直接贴代码,直接调用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 = FromBaseUrl(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);
 IBaseUrlEncoder urlEncoder = new JwtBaseUrlEncoder();
 RSAlgorithmFactory rS256Algorithm = new RSAlgorithmFactory(() =>
 {
 RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
 rsa.ImportParameters(
 new RSAParameters()
 {
 Modulus = FromBaseUrl(modulus),
 Exponent = FromBaseUrl(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[] FromBaseUrl(string baseUrl)
 {
 string padded = baseUrl.Length % 4 == 0
 ? baseUrl : baseUrl + "====".Substring(baseUrl.Length % 4);
 string base = padded.Replace("_", "/")
 .Replace("-", "+");
 return Convert.FromBaseString(base);
}

下载本文
显示全文
专题