欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2023-10-17 15:12:54
情景:公司项目基于.net4.0,web客户端实现单点登录需要自己解密id_token,对于jwt解密,.net提供了identitymodel类库,但是4.0中该类库不可...

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。