如果我传递序列化的 json 数据,它会出现在 http 请求中的啥位置?

Posted

技术标签:

【中文标题】如果我传递序列化的 json 数据,它会出现在 http 请求中的啥位置?【英文标题】:If i pass serialized json data, where does that appear in the http request?如果我传递序列化的 json 数据,它会出现在 http 请求中的什么位置? 【发布时间】:2021-08-12 06:18:14 【问题描述】:

我正在尝试这样做:将 http 验证令牌插入到序列化的 JSON 数据中。我已经有能力在 JSON 中正常传递它,也可以使用自定义授权扩展在标头中传递它。我想做的是,在验证器中,如果请求不在标头数据或表单数据中,则反序列化传递的数据并在那里查看。我实际上无法在请求中找到数据。当我读取传递的数据(84 字节)时,我得到了一堆数字。

这是防伪验证器:

    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];
            //try header first
            var token = httpContext.Request.Headers["__RequestVerificationToken"];
            //try normal method
            if (token == null)
            
                for(int cl = 0; cl < httpContext.Request.Form.Keys.Count; cl++)
                
                    if (httpContext.Request.Form.Keys[cl] == "__RequestVerificationToken")
                    
                        token = httpContext.Request.Form[httpContext.Request.Form.Keys[cl]];
                    
                
            
            if (token == null) 
            
                //this section isn't finding the passed data
                //get here if form stringified    
                System.IO.Stream str; String strmContents;
                Int32 counter, strLen, strRead;
                // Create a Stream object.
                str = httpContext.Request.InputStream;
                // Find number of bytes in stream.
                strLen = Convert.ToInt32(str.Length);
                // Create a byte array.
                byte[] strArr = new byte[strLen];
                // Read stream into byte array.
                strRead = str.Read(strArr, 0, strLen);

                // Convert byte array to a text string.
                strmContents = "";
                for (counter = 0; counter < strLen; counter++)
                
                    strmContents = strmContents + strArr[counter].ToString();
                
                
                token = strmContents; //just so i can debug the returned token
            
            //if both fail, attempt to check stringified data for matching token.
            AntiForgery.Validate(cookie != null ? cookie.Value : null, token);
        
    

下面是我们序列化表单数据的一些示例代码:

            $.ajax(
            type: "POST",
            headers: appendVerificationToken(),
            url: "/OrderSettlement/SessionApplyRatesCancel",
            data: JSON.stringify( key: data.key ),
            contentType: "application/json",
            success: function () 
                /* decided to NOT close the window (just cancel and show the [CANCELLED] description)
                // on success, close the owning popup
                runFuncByNameSingleParameter(_owningPopup.Close);
                */
            
        );

正如我所说,在标头中传递它是可行的,但我希望能够将它添加到数据中,但我在解析它的请求中找不到它。

【问题讨论】:

由于您提交请求的方式,JSON 构成了请求的整个正文。它不是表单编码的数据。您可以通过多种方式获得该身体。一种方法(虽然不一定是最好的)是string requestBody = await httpRequest.Content.ReadAsStringAsync(); 我会尝试这样阅读,看看我是否能得到一个好的结果,谢谢。 虽然我无法像您发布的那样阅读它(这是一个注释,所以我认为我不能使其异步)并且它内置在 filtercontext 中,您关于它成为整个请求的信息很好足以让我找到正确的解决方案。这有效:使用 (var reader = new StreamReader(httpContext.Request.InputStream)) json = reader.ReadToEnd(); 如果您发布某种答案,我会接受。与此同时,我要留下一个“占位符”的答案。 【参考方案1】:

感谢Ouroborus,我能够想出一个解决方案。 这有效:

           string json;
            var position = httpContext.Request.InputStream.Position;
            using (var reader = new StreamReader(httpContext.Request.InputStream, Encoding.UTF8, false, 8192, true))
             
                json = reader.ReadToEnd();
                //you MUST reset the input stream to start or you will break post.
                httpContext.Request.InputStream.Seek(position, SeekOrigin.Begin);
                try
                
                    var jsonObj = Json.Decode(json); //attempt to parse into json object.  
                    token = jsonObj["__RequestVerificationToken"];
                
                catch
                
                    //eat the parse errors.  That simply means it's not json.
                
            

我希望它可以帮助别人。请注意,您必须将流重置为零,这正是我正在做的,否则控制器函数将不会接收任何传递的数据。

【讨论】:

以上是关于如果我传递序列化的 json 数据,它会出现在 http 请求中的啥位置?的主要内容,如果未能解决你的问题,请参考以下文章

JSON.net 直接从 oledbconnection 序列化

通过隐藏字段传递 JSON 序列化数据

json串向后台传递数值自动四舍五入的问题

如何在ajax返回时解析字符串的JSON列表?

将来自 Axios 的 JSON 响应传递给数据对象但出现错误

在 swift 5.2 con Alamofire 中将数据(json)传递给另一个控制器