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

序列化JSON在HTTP请求中的位置及防伪令牌读取问题

问题根因

你当前无法正确读取JSON请求体的核心原因有3个:

  • 字节转字符串逻辑错误:你没有用字符编码解码字节数组,而是将每个字节的十进制数值直接转字符串拼接,比如字节0x7B对应字符{,直接ToString()会得到字符串123,最终结果自然是一串无意义的数字
  • 请求流指针偏移:Request.Form读取操作会将InputStream的读取指针移动到流末尾,后续直接调用Read方法无法读取到任何内容
  • 缺少JSON反序列化步骤:你当前直接把整个请求体当作令牌值,没有从JSON结构中提取__RequestVerificationToken对应的字段值

修复步骤

1. 前端代码调整

提交JSON时需要把防伪令牌加入序列化对象中,示例如下:

$.ajax({
    type: "POST",
    // 如果你不需要头传令牌可以去掉headers参数
    // headers: appendVerificationToken(),
    url: "/OrderSettlement/SessionApplyRatesCancel",
    // 加入__RequestVerificationToken字段
    data: JSON.stringify({ 
        key: data.key,
        __RequestVerificationToken: "你的防伪令牌值" 
    }),
    contentType: "application/json",
    success: function () {
        // 原有逻辑
    }
});

2. C#验证过滤器代码调整

需要先重置请求流位置,用正确的编码转字符串,再反序列化提取令牌:

using Newtonsoft.Json.Linq; // 如果你用System.Text.Json可以替换对应命名空间

namespace DispatchCrude.Extensions
{
    [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class,
                AllowMultiple = false, Inherited = true)]
    public sealed class ValidateHeaderAntiForgeryTokenAttribute : FilterAttribute, IAuthorizationFilter
    {
        public void OnAuthorization(AuthorizationContext filterContext)
        {
            if (filterContext == null)
            {
                throw new ArgumentNullException("filterContext");
            }

            var httpContext = filterContext.HttpContext;
            var cookie = httpContext.Request.Cookies[AntiForgeryConfig.CookieName];
            // 优先从请求头取令牌
            var token = httpContext.Request.Headers["__RequestVerificationToken"];
            // 从表单取令牌
            if (token == null && httpContext.Request.Form.AllKeys.Contains("__RequestVerificationToken"))
            {
                token = httpContext.Request.Form["__RequestVerificationToken"];
            }
            // 从JSON请求体取令牌
            if (token == null && httpContext.Request.ContentType == "application/json")
            {
                // 重置请求流指针到起始位置
                httpContext.Request.InputStream.Position = 0;
                // 用UTF8编码将流转成字符串
                using (var reader = new StreamReader(httpContext.Request.InputStream, System.Text.Encoding.UTF8))
                {
                    var jsonBody = reader.ReadToEnd();
                    // 反序列化JSON提取令牌字段
                    if (!string.IsNullOrEmpty(jsonBody))
                    {
                        var jsonObj = JObject.Parse(jsonBody);
                        token = jsonObj.Value<string>("__RequestVerificationToken");
                    }
                    // 再次重置流位置,避免后续Action的模型绑定读取不到请求体
                    httpContext.Request.InputStream.Position = 0;
                }
            }
            // 验证令牌
            AntiForgery.Validate(cookie != null ? cookie.Value : null, token);
        }
    }
}

注意事项

  • 如果你的项目用System.Text.Json做序列化,将JObject.Parse替换为对应JsonSerializer解析逻辑即可
  • 非JSON类型的请求不会走到JSON解析逻辑,不会影响原有表单、头传令牌的验证逻辑
  • 读取完请求体后必须重置流指针位置,否则后续Action接收的参数会为空

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 16:27:02