将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
相关产品推荐
相关产品推荐

