【问题标题】:C# JWT VertificationC# JWT 验证
【发布时间】:2017-02-17 23:42:00
【问题描述】:

我正在尝试在站点 (c#) 上进行 firebase 身份验证。我需要验证登录令牌。

我得到令牌没问题,如果我使用令牌和来自令牌的公钥转到https://jwt.io/,它会返回签名有效。

我的问题是我不知道如何在 c# 中验证令牌。

我在令牌和公钥中发送了以下代码(没有 ---BEGIN 证书和结束证书--)。

我收到错误序列大小:3 参数名称:seq

我正在使用充气城堡进行加密。我不知道我哪里出错了。我试图验证的一切都没有奏效。

如果有任何帮助,我将不胜感激。

谢谢。

public static string Decode(string token,string key, bool verify = true)
    {
        //  HttpContext.Current.Response.Write(key);
        //   HttpContext.Current.Response.End();
        string[] parts = token.Split('.');
        string header = parts[0];
        string payload = parts[1];
        byte[] crypto = Base64UrlDecode(parts[2]);

        string headerJson = Encoding.UTF8.GetString(Base64UrlDecode(header));
        JObject headerData = JObject.Parse(headerJson);

        string payloadJson = Encoding.UTF8.GetString(Base64UrlDecode(payload));
        JObject payloadData = JObject.Parse(payloadJson);

        if (verify)
        {
            var keyBytes = Convert.FromBase64String(key); // your key here

            AsymmetricKeyParameter asymmetricKeyParameter = PublicKeyFactory.CreateKey(keyBytes);
            RsaKeyParameters rsaKeyParameters = (RsaKeyParameters)asymmetricKeyParameter;
            RSAParameters rsaParameters = new RSAParameters();
            rsaParameters.Modulus = rsaKeyParameters.Modulus.ToByteArrayUnsigned();
            rsaParameters.Exponent = rsaKeyParameters.Exponent.ToByteArrayUnsigned();
            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
            rsa.ImportParameters(rsaParameters);

            SHA256 sha256 = SHA256.Create();
            byte[] hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(parts[0] + '.' + parts[1]));

            RSAPKCS1SignatureDeformatter rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa);
            rsaDeformatter.SetHashAlgorithm("SHA256");
            if (!rsaDeformatter.VerifySignature(hash, FromBase64Url(parts[2])))
                throw new ApplicationException(string.Format("Invalid signature"));
        }

        return payloadData.ToString();
    }

    private 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);
    }

    // from JWT spec
    private static byte[] Base64UrlDecode(string input)
    {
        var output = input;
        output = output.Replace('-', '+'); // 62nd char of encoding
        output = output.Replace('_', '/'); // 63rd char of encoding
        switch (output.Length % 4) // Pad with trailing '='s
        {
            case 0: break; // No pad chars in this case
            case 1: output += "==="; break; // Three pad chars
            case 2: output += "=="; break; // Two pad chars
            case 3: output += "="; break; // One pad char
            default: throw new System.Exception("Illegal base64url string!");
        }
        var converted = Convert.FromBase64String(output); // Standard base64 decoder
        return converted;
    }

【问题讨论】:

  • 你为什么要自己做这个?有成熟的库来处理 jwt。 open sourcemsoft

标签: c# jwt


【解决方案1】:

.NET 中有非常好的预定义库来支持应用程序中的 JWT。 System.IdentityModel.Tokens.Jwt 和 Microsoft.IdentityModel.Tokens 有很多有用的东西。我最近在 WebAPI 应用程序中实现了 JWT 令牌创建和身份验证。我写这个是为了验证 JWT。

using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using Microsoft.IdentityModel.Tokens;

public class JwtTokenValidator
    {
        public ClaimsPrincipal ValidateToken(string jwtToken)
        {
            SecurityToken securityToken;
            var validationParameters = new TokenValidationParameters()
            {
                ValidIssuer = "ValidTokenIssuerName",
                ValidAudience = "ValidTokenAudienceName",
                ValidateIssuerSigningKey = true,
                ValidateAudience = true,
                ValidateIssuer = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.Default.GetBytes("ValidTokenSigningKey"))
            };

        var recipientTokenHandler = new JwtSecurityTokenHandler();
        var claimsPrincipal = recipientTokenHandler.ValidateToken(jwtToken, validationParameters, out securityToken);
        return claimsPrincipal;
    }
} 

您需要根据您的应用程序使用有效详细信息更新上述字符串详细信息,用于创建 JWT。 我还分享了我编写的从 AuthenticationTicket 创建 JWT 的代码。我希望它会有所帮助。

using System;
using System.IdentityModel.Tokens.Jwt;
using System.Text;
using Microsoft.IdentityModel.Tokens;
using Microsoft.Owin.Security;

public class JwtTokenFormatter : ISecureDataFormat<AuthenticationTicket>
    {
        private readonly JwtSecurityTokenHandler _tokenHandler;
        public JwtTokenFormatter()
        {
            _tokenHandler = new JwtSecurityTokenHandler();

        }
        public string Protect(AuthenticationTicket data)
        {
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Audience = "ValidTokenAudienceName",
                Issuer = "ValidTokenIssuerName",
                IssuedAt = DateTime.UtcNow,
                NotBefore = DateTime.UtcNow,
                Expires = DateTime.UtcNow.AddHours(24),
                Subject = data.Identity,
                SigningCredentials =
                    new SigningCredentials(
                        new SymmetricSecurityKey(Encoding.Default.GetBytes("ValidTokenSigningKey")),
                        SecurityAlgorithms.HmacSha256Signature)
            };

            return _tokenHandler.CreateEncodedJwt(tokenDescriptor);
        }

        public AuthenticationTicket Unprotect(string protectedText)
        {
            throw new NotImplementedException();
        }
    }

【讨论】:

  • 您正在使用对称密钥。有很多使用对称密钥的例子,但@chiefBacon 的问题是 AsymmetricKey
猜你喜欢
  • 2018-06-12
  • 2016-07-10
  • 2017-04-05
  • 2020-12-15
  • 2018-08-06
  • 1970-01-01
  • 2020-11-07
  • 2023-03-12
  • 2018-11-08
相关资源
最近更新 更多