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

读取JWT声明时西里尔字母编码异常问题求助

问题:JWT中部分声明的西里尔字母显示为\u转义字符

开发了一个接收Webhook的程序,需读取RS256签名的JWT内容。验证公钥已具备,但读取时发现前两个声明(SidePayer、SideRecipient)中的西里尔字母被解析为\u转义字符,后续声明(如purpose)则显示正常。

读取Token代码

public async Task<IActionResult> test()
{
    using (var reader = new StreamReader(Request.Body))
    {
        var body = await reader.ReadToEndAsync();

        RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
        rsa.ImportParameters(
            new RSAParameters()
            {
                Modulus = FromBase64Url("rwm77av7GIttq-JF1itEgLCGEZW_zz16RlUQVYlLbJtyRSu61fCec_rroP6PxjXU2uLzUOaGaLgAPeUZAJrGuVp9nryKgbZceHckdHDYgJd9TsdJ1MYUsXaOb9joN9vmsCscBx1lwSlFQyNQsHUsrjuDk-opf6RCuazRQ9gkoDCX70HV8WBMFoVm-YWQKJHZEaIQxg_DU4gMFyKRkDGKsYKA0POL-UgWA1qkg6nHY5BOMKaqxbc5ky87muWB5nNk4mfmsckyFv9j1gBiXLKekA_y4UwG2o1pbOLpJS3bP_c95rm4M9ZBmGXqfOQhbjz8z-s9C11i-jmOQ2ByohS-ST3E5sqBzIsxxrxyQDTw--bZNhzpbciyYW4GfkkqyeYoOPd_84jPTBDKQXssvj8ZOj2XboS77tvEO1n1WlwUzh8HPCJod5_fEgSXuozpJtOggXBv0C2ps7yXlDZf-7Jar0UYc_NJEHJF-xShlqd6Q3sVL02PhSCM-ibn9DN9BKmD"),
                Exponent = FromBase64Url("AQAB")
            });
        var validationParameters = new TokenValidationParameters
        {
            RequireExpirationTime = true,
            RequireSignedTokens = true,
            ValidateAudience = false,
            ValidateIssuer = false,
            ValidateLifetime = false,
            IssuerSigningKey = new RsaSecurityKey(rsa)
        };

        SecurityToken validatedSecurityToken;
        var handler = new JwtSecurityTokenHandler();
        handler.ValidateToken(body, validationParameters, out validatedSecurityToken);
        JwtSecurityToken? validatedJwt = validatedSecurityToken as JwtSecurityToken;

        if (validatedJwt != null)
        {
            foreach (var claim in validatedJwt.Claims.ToList())
            {
                Console.WriteLine($"{claim.Type}: {claim.Value}");
            }
            return Ok();
        }
        else
        {
            return BadRequest("Invalid token");
        }
    }
}

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

控制台输出

SidePayer: {"bankCode": "000000000", "bankName": "\u041e\u041e\u041e \"\u0411\u0410\u041d\u041a \u0422\u041e\u0427\u041a\u0410\"", "bankCorrespondentAccount": "00000000000000000000", "account": "00000000000000000000", "name": "\u0418\u041f \u0422\u0435\u0441\u0442", "amount": "40.0", "currency": "RUB", "inn": "0000000000", "kpp": "0000000000"}
SideRecipient: {"bankCode": "000000000", "bankName": "\u041e\u041e\u041e \"\u0411\u0410\u041d\u041a \u0422\u041e\u0427\u041a\u0410\"", "bankCorrespondentAccount": "00000000000000000000", "account": "00000000000000000000", "name": "\u0418\u041f \u0422\u0435\u0441\u0442", "amount": "40.0", "currency": "RUB", "inn": "0000000000", "kpp": "0000000000"}
purpose: Тестовое назначение платежа
documentNumber: 00000
date: 2018-10-01

解决方案

问题原因

SidePayer和SideRecipient的声明值是嵌套的JSON字符串,JwtSecurityTokenHandler解析时仅将其作为普通字符串处理,未自动反序列化嵌套结构,导致字符串内的Unicode转义字符(\u开头)未被解码为实际西里尔字母;而purpose等声明是直接的字符串类型,因此显示正常。

解决步骤

针对嵌套JSON类型的声明,手动对其值进行反序列化操作,即可自动解码Unicode转义字符。以下提供两种实现方式:

方式1:使用Newtonsoft.Json(Json.NET)

修改遍历Claims的逻辑,对目标声明进行反序列化:

if (validatedJwt != null)
{
    foreach (var claim in validatedJwt.Claims.ToList())
    {
        if (claim.Type is "SidePayer" or "SideRecipient")
        {
            // 反序列化嵌套JSON,自动解码Unicode转义
            var decodedObject = Newtonsoft.Json.JsonConvert.DeserializeObject(claim.Value);
            // 格式化输出,也可直接输出decodedObject
            var formattedOutput = Newtonsoft.Json.JsonConvert.SerializeObject(decodedObject, Newtonsoft.Json.Formatting.Indented);
            Console.WriteLine($"{claim.Type}: {formattedOutput}");
        }
        else
        {
            Console.WriteLine($"{claim.Type}: {claim.Value}");
        }
    }
    return Ok();
}

方式2:使用System.Text.Json(.NET Core内置)

若使用.NET Core 3.0+,可直接用内置的Json序列化器:

if (validatedJwt != null)
{
    foreach (var claim in validatedJwt.Claims.ToList())
    {
        if (claim.Type is "SidePayer" or "SideRecipient")
        {
            // 反序列化为JsonElement,ToString时自动解码转义
            var decodedElement = System.Text.Json.JsonSerializer.Deserialize<System.Text.Json.JsonElement>(claim.Value);
            Console.WriteLine($"{claim.Type}: {decodedElement.ToString()}");
        }
        else
        {
            Console.WriteLine($"{claim.Type}: {claim.Value}");
        }
    }
    return Ok();
}

额外优化:直接解析整个Payload

如果需要处理多个嵌套JSON声明,也可以直接解析整个JWT的Payload,避免逐个判断:

if (validatedJwt != null)
{
    // 将Payload序列化为JSON字符串
    var payloadJson = validatedJwt.Payload.SerializeToJson();
    // 反序列化为JObject(Newtonsoft.Json)
    var payload = Newtonsoft.Json.JsonConvert.DeserializeObject<Newtonsoft.Json.Linq.JObject>(payloadJson);
    
    // 直接访问各声明,自动解码转义字符
    Console.WriteLine($"SidePayer: {payload["SidePayer"]}");
    Console.WriteLine($"purpose: {payload["purpose"]}");
    
    return Ok();
}

内容的提问来源于stack exchange,提问作者darrso

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 19:24:53