基于.net4.0實(shí)現(xiàn)IdentityServer4客戶端JWT解密
情景:公司項(xiàng)目基于.net4.0,web客戶端實(shí)現(xiàn)單點(diǎn)登錄需要自己解密id_token,對(duì)于jwt解密,.net提供了IdentityModel類庫,但是4.0中該類庫不可用,所以自己實(shí)現(xiàn)了解密方法..
使用了類庫:鏈接地址
下面直接貼代碼,直接調(diào)用DecodeJWT方法就行,參數(shù)為id_token,key默認(rèn)為空字符串"",
代碼
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驗(yàn)證失敗");
//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);
}
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
如何為CheckBoxList和RadioButtonList添加滾動(dòng)條
這篇文章主要介紹了為CheckBoxList和RadioButtonList添加滾動(dòng)條的方法,感興趣的小伙伴們可以參考一下2016-07-07
Asp.Net其他頁面如何調(diào)用Web用戶控件寫的分頁
這篇文章主要介紹了Asp.Net其他頁面如何調(diào)用Web用戶控件寫的分頁,需要的朋友可以參考下2014-05-05
asp.net4.0框架下驗(yàn)證機(jī)制失效的原因及處理辦法
asp.net4.0框架下驗(yàn)證機(jī)制失效的原因及處理辦法,需要的朋友可以參考一下2013-06-06
.NET實(shí)現(xiàn)倉儲(chǔ)Repository(AI)的操作方法
倉儲(chǔ)模式是一種在應(yīng)用程序中使用的設(shè)計(jì)模式,它將數(shù)據(jù)訪問邏輯與業(yè)務(wù)邏輯分離,通過倉儲(chǔ)接口和倉儲(chǔ)實(shí)現(xiàn)類,您可以定義和實(shí)現(xiàn)數(shù)據(jù)的增刪改查操作,這篇文章主要介紹了.NET?實(shí)現(xiàn)倉儲(chǔ)Repository(AI),需要的朋友可以參考下2023-09-09

