基于.net4.0實(shí)現(xiàn)IdentityServer4客戶端JWT解密
情景:公司項(xiàng)目基于.net4.0,web客戶端實(shí)現(xiàn)單點(diǎn)登錄需要自己解密id_token,對(duì)于jwt解密,.net提供了IdentityModel類(lèi)庫(kù),但是4.0中該類(lèi)庫(kù)不可用,所以自己實(shí)現(xiàn)了解密方法..
使用了類(lèi)庫(kù):鏈接地址
下面直接貼代碼,直接調(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已過(guò)期");
//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);
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
datagrid綁定list沒(méi)有數(shù)據(jù) 表頭不顯示的解決方法
datagrid綁定list沒(méi)有數(shù)據(jù) 表頭不顯示的問(wèn)題,那是因?yàn)?綁定了null,你給list new一下就好 表頭就會(huì)有啦2013-05-05
ASP.NET實(shí)現(xiàn)個(gè)人信息注冊(cè)頁(yè)面并跳轉(zhuǎn)顯示
這篇文章主要介紹了ASP.NET實(shí)現(xiàn)個(gè)人信息注冊(cè)頁(yè)面并跳轉(zhuǎn)顯示的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-12-12
獲取轉(zhuǎn)向地址的URL的源文件(可自定義REFER)
獲取轉(zhuǎn)向地址的URL的源文件(可自定義REFER)...2006-09-09
WinForm中窗體間的數(shù)據(jù)傳遞交互的一些方法
通過(guò)子窗口向外引發(fā)一個(gè)事件,父窗口去實(shí)現(xiàn)該事件,我們可以再不關(guān)閉父窗口和子窗口的情況下進(jìn)行數(shù)據(jù)的傳輸顯示2012-12-12
asp.net 基于forms驗(yàn)證的目錄角色權(quán)限的實(shí)現(xiàn)
一個(gè)系統(tǒng)中經(jīng)常有多種身份的用戶,往往要根據(jù)其身份來(lái)控制目錄的訪問(wèn)權(quán)限。asp.net提供了forms驗(yàn)證,能夠輕易的在配置文件中設(shè)置用戶對(duì)目錄的訪問(wèn)權(quán)限.2009-11-11
詳解Asp.net web.config customErrors 如何設(shè)置
這篇文章主要介紹了詳解Asp.net web.config customErrors 如何設(shè)置,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
.NET事件監(jiān)聽(tīng)機(jī)制的局限與擴(kuò)展分析
這篇文章主要介紹了.NET事件監(jiān)聽(tīng)機(jī)制的局限與擴(kuò)展,詳細(xì)分析了.NET事件監(jiān)聽(tīng)機(jī)制的機(jī)制與優(yōu)劣,有助于更好的理解.NET的運(yùn)行原理,需要的朋友可以參考下2014-11-11

