You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 3.5项目中如何使用System.IdentityModel.Tokens.Jwt 5.2.1验证JWT令牌?

在.NET Framework 3.5中验证JWT令牌的解决方案

你遇到的问题很典型:你之前在.NET Framework 4.5.2中用的Microsoft.IdentityModel.Tokens和JwtSecurityTokenHandler这套官方JWT组件,是从.NET Framework 4.5才开始引入的,.NET 3.5根本没有这些类库,直接移植代码肯定会报错。下面给你两种可行的解决思路:

方案一:使用兼容.NET 3.5的第三方JWT库

最省心的方式是用第三方库,比如JWT.NET(旧版本支持.NET 3.5)。你需要找支持.NET 3.5的版本,比如v3.x系列(新版本已经不再支持3.5了)。

安装步骤

如果你用NuGet包管理器,搜索JWT并选择版本3.0.2(这个版本明确支持.NET 3.5);如果是手动引用,去下载对应的DLL文件。

验证令牌的示例代码

using System;
using System.Collections.Generic;
using JWT;
using JWT.Algorithms;
using JWT.Serializers;

namespace TokenValidator
{
    public class TokenValidationHelper
    {
        public static bool ValidateToken(string token, string secretKey)
        {
            try
            {
                var serializer = new JsonNetSerializer();
                var provider = new UtcDateTimeProvider();
                var validator = new JwtValidator(serializer, provider);
                var urlEncoder = new JwtBase64UrlEncoder();
                var algorithm = new HMACSHA256Algorithm(); // 根据你的令牌签名算法调整,比如HS512等

                var decoder = new JwtDecoder(serializer, validator, urlEncoder, algorithm);
                
                // 解码并验证令牌,验证通过会返回Payload,失败则抛出异常
                var payload = decoder.DecodeToObject<Dictionary<string, object>>(token, secretKey, verify: true);
                
                // 这里可以额外验证Payload里的自定义字段,比如exp(过期时间)、iss(签发者)等
                if (payload.ContainsKey("exp"))
                {
                    var expTime = UnixTimeStampToDateTime(Convert.ToDouble(payload["exp"]));
                    if (expTime < DateTime.UtcNow)
                    {
                        return false;
                    }
                }
                
                return true;
            }
            catch (TokenExpiredException)
            {
                // 令牌过期
                return false;
            }
            catch (SignatureVerificationException)
            {
                // 签名验证失败
                return false;
            }
            catch (Exception)
            {
                // 其他错误
                return false;
            }
        }

        private static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
        {
            var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
            return dtDateTime;
        }
    }
}

方案二:手动解析并验证JWT令牌

如果不想依赖第三方库,你可以手动解析JWT的结构,因为JWT本质是由Base64Url编码的三部分(Header、Payload、Signature)组成的字符串,用.分隔。

手动验证的核心步骤

  • 拆分令牌为Header、Payload、Signature三部分
  • 对Header和Payload进行Base64Url解码,获取内容
  • 重新拼接Header和Payload(用.连接),然后用对应的签名算法(比如HMACSHA256)结合密钥计算签名,和原令牌的Signature对比
  • 额外验证Payload里的过期时间、签发者等自定义字段

示例代码(HS256签名算法为例)

using System;
using System.Text;
using System.Security.Cryptography;
using System.Web.Script.Serialization; // 需要引用System.Web.Extensions.dll

namespace TokenValidator
{
    public class ManualTokenValidator
    {
        public static bool ValidateToken(string token, string secretKey)
        {
            var parts = token.Split('.');
            if (parts.Length != 3)
                return false;

            var header = parts[0];
            var payload = parts[1];
            var signature = parts[2];

            // 验证签名
            var encodedHeaderPayload = $"{header}.{payload}";
            var computedSignature = ComputeHmacSha256Signature(encodedHeaderPayload, secretKey);
            if (computedSignature != signature)
                return false;

            // 解码Payload并验证过期时间
            var decodedPayload = Base64UrlDecode(payload);
            var serializer = new JavaScriptSerializer();
            var payloadData = serializer.Deserialize<Dictionary<string, object>>(decodedPayload);
            
            if (payloadData.ContainsKey("exp"))
            {
                var expTime = UnixTimeStampToDateTime(Convert.ToDouble(payloadData["exp"]));
                if (expTime < DateTime.UtcNow)
                    return false;
            }

            // 这里可以添加更多自定义验证逻辑,比如iss、aud等
            return true;
        }

        private static string ComputeHmacSha256Signature(string input, string secretKey)
        {
            var encoding = new UTF8Encoding();
            var secretBytes = encoding.GetBytes(secretKey);
            var inputBytes = encoding.GetBytes(input);

            using (var hmac = new HMACSHA256(secretBytes))
            {
                var hashBytes = hmac.ComputeHash(inputBytes);
                return Base64UrlEncode(hashBytes);
            }
        }

        private static string Base64UrlEncode(byte[] input)
        {
            var base64 = Convert.ToBase64String(input);
            return base64.Replace('+', '-').Replace('/', '_').TrimEnd('=');
        }

        private static string Base64UrlDecode(string input)
        {
            input = input.Replace('-', '+').Replace('_', '/');
            switch (input.Length % 4)
            {
                case 2: input += "=="; break;
                case 3: input += "="; break;
            }
            var decodedBytes = Convert.FromBase64String(input);
            return Encoding.UTF8.GetString(decodedBytes);
        }

        private static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
        {
            var dtDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
            dtDateTime = dtDateTime.AddSeconds(unixTimeStamp).ToLocalTime();
            return dtDateTime;
        }
    }
}

额外注意事项

  • .NET Framework 3.5默认使用TLS 1.0,而现在大多数身份提供商要求TLS 1.2及以上。如果你的验证过程需要调用远程接口获取公钥(比如RS256签名的情况),需要在代码开头添加:
    System.Net.ServicePointManager.SecurityProtocol = (System.Net.SecurityProtocolType)3072; // TLS 1.2
    
  • 如果你用的是RS256等非对称签名算法,手动验证会更复杂,推荐优先用第三方库来处理。

内容的提问来源于stack exchange,提问作者Setu Kumar Basak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:02:51