情景:公司项目基于.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);
}
下载本文