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

将JWT Token从请求体传递至请求头时遇JsonException问题求助

问题:从请求体提取JWT Token时遇到JsonException错误

问题背景

尝试将请求体中的JWT Token转移到请求头,编写代码后出现JSON解析失败的异常。

初始代码

OnMessageReceived = ctx => {
    ctx.Request.EnableBuffering();

    //var test = ctx.Request.Method;
    //var test2 = ctx.Request.Body;

    //var bodyAsText = new System.IO.StreamReader(ctx.Request.Body).ReadToEnd();
    //var body2 = JsonSerializer.Deserialize<dynamic>(bodyAsText);
    using (var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8, true, 1024, true))
    {
        var jsonBody = reader.ReadToEnd();

        /* var keyValueParis = jsonBody.Split('&')
            .Select(value => value.Split('='))
            .ToDictionary(pair => Uri.UnescapeDataString(pair[0]), pair => Uri.UnescapeDataString(pair[1])); */

        var options = new JsonSerializerOptions
        {
            PropertyNameCaseInsensitive = true
        };
        //var data = Newtonsoft.Json.JsonConvert.DeserializeObject<JwtSerialization>(bodyAsText);

        var body = JsonSerializer.Deserialize<dynamic>(jsonBody, options);
        ctx.Request.Body.Position = 0;
        if (body != null)
        {
            ctx.Token = body.Token;
        }

        Console.WriteLine(jsonBody);
        ctx.Request.Body.Position = 0;
    }

    return Task.CompletedTask;
}

错误信息

Exception has occurred: CLR/System.Text.Json.JsonException
发生类型为'System.Text.Json.JsonException'的异常,未在用户代码中处理:''A'是无效的值起始字符。路径: $ | 行号: 0 | 字节位置: 0。'

请求体格式(PowerShell发送)

$body:                                                           
Name                           Value                                           
----                           -----                                           
Authorization                  Bearer eyJ1fXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1…
Content-Type                   application/json

尝试过的自定义类

public class JwtSerialization
{
    public string TokenType { get; set; }
    public string AccessToken { get; set; }
}

更新后的代码

using (var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8, true, 1024, true))
{
    
    var jsonBody = reader.ReadToEnd();

    if(String.IsNullOrEmpty(jsonBody) == false){
        var keyValueParis = jsonBody.Split('&')
            .Select(value => value.Split('='))
            .ToDictionary(pair => Uri.UnescapeDataString(pair[0]), pair => Uri.UnescapeDataString(pair[1]));

        if(String.IsNullOrEmpty(keyValueParis["Authorization"]) == false){
            
            var token = keyValueParis["Authorization"].Replace("Bearer", "").Replace("+", "");

            if(new System.Text.RegularExpressions.Regex(@"^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$").IsMatch(token ?? String.Empty)){
            
                //var options = new JsonSerializerOptions
                //{
                //    PropertyNameCaseInsensitive = true
                //};
                //var jsonString = JsonSerializer.Serialize(keyValueParis, options);
                //var jsonData = JsonSerializer.Deserialize<JsonElement>(jsonString, options);
                //var data = Newtonsoft.Json.JsonConvert.DeserializeObject<JwtSerialization>(bodyAsText);

                //var body = JsonSerializer.Deserialize<dynamic>(jsonBody, options);
                ctx.Request.Body.Position = 0;
                ctx.Token = token;
                
                ctx.Request.Body.Position = 0;
            }
        }
    }
}

解决方案

问题根源

错误核心是请求体格式与声明的Content-Type不匹配:PowerShell发送的是键值对格式(类似form-urlencoded),但标记了Content-Type: application/json,导致代码尝试用JSON反序列化非JSON内容,触发解析异常。

修复步骤

1. 统一请求体格式与Content-Type

  • 若使用JSON格式:调整PowerShell请求体为标准JSON结构,确保Content-Type正确:
    $body = @{
        Authorization = "Bearer eyJ1fXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1..."
    } | ConvertTo-Json
    $headers = @{ "Content-Type" = "application/json" }
    Invoke-RestMethod -Uri "你的接口地址" -Method Post -Body $body -Headers $headers
    
  • 若使用form-urlencoded格式:修改Content-Type为application/x-www-form-urlencoded,保持键值对请求体。

2. 代码适配对应格式

适配JSON格式的代码示例
OnMessageReceived = ctx => {
    ctx.Request.EnableBuffering();

    using (var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8, true, 1024, true))
    {
        var jsonBody = reader.ReadToEnd();
        ctx.Request.Body.Position = 0;

        if (!string.IsNullOrEmpty(jsonBody))
        {
            try
            {
                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true
                };
                var body = JsonSerializer.Deserialize<JwtRequest>(jsonBody, options);
                
                if (body?.Authorization != null && body.Authorization.StartsWith("Bearer "))
                {
                    // 移除Bearer前缀及空格,提取纯Token
                    ctx.Token = body.Authorization["Bearer ".Length..].Trim();
                }
            }
            catch (JsonException ex)
            {
                // 记录解析失败日志,避免中断请求
                Console.WriteLine($"JSON解析失败: {ex.Message}");
            }
        }

        ctx.Request.Body.Position = 0;
        return Task.CompletedTask;
    }
}

// 匹配JSON结构的自定义类
public class JwtRequest
{
    public string Authorization { get; set; }
}
适配form-urlencoded格式的代码优化
OnMessageReceived = ctx => {
    ctx.Request.EnableBuffering();

    using (var reader = new StreamReader(ctx.Request.Body, Encoding.UTF8, true, 1024, true))
    {
        var bodyText = reader.ReadToEnd();
        ctx.Request.Body.Position = 0;

        if (!string.IsNullOrEmpty(bodyText))
        {
            // 仅处理form-urlencoded格式的请求
            var contentType = ctx.Request.Headers.ContentType.ToString();
            if (contentType.Contains("application/x-www-form-urlencoded"))
            {
                var keyValuePairs = bodyText.Split('&')
                    .Select(kv => kv.Split(new[] { '=' }, 2)) // 限制分割为2份,避免值包含=的情况
                    .Where(kv => kv.Length == 2)
                    .ToDictionary(
                        kv => Uri.UnescapeDataString(kv[0]),
                        kv => Uri.UnescapeDataString(kv[1])
                    );

                if (keyValuePairs.TryGetValue("Authorization", out var authValue))
                {
                    var token = authValue.Replace("Bearer ", "").Trim();
                    // 验证Token格式
                    if (new System.Text.RegularExpressions.Regex(@"^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$").IsMatch(token))
                    {
                        ctx.Token = token;
                    }
                }
            }
        }

        ctx.Request.Body.Position = 0;
        return Task.CompletedTask;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:28:13