在Json.net c#中遍历和htmlcode字符串

本文关键字:htmlcode 字符串 遍历 Json net | 更新日期: 2023-09-27 18:08:10

我努力在json中安全地编码类似html的文本。文本应写入<textarea>,通过ajax传输到服务器(.net45 mvc),并存储在json字符串的数据库中。

当传输到服务器时,我得到了著名的"一个潜在危险的请求"。表单值被检测到500服务器错误。为了避免此消息,我在传输的模型上使用了[AllowHtml]属性。通过这样做,我打开了xss漏洞,以防有人粘贴{ "key1": "<script>alert('"danger!'")</script>" }。因此,我想使用像

这样的东西
tableData.Json = AntiXssEncoder.HtmlEncode(json, true);

问题是我不能在完整的json字符串上这样做,因为它会呈现像

这样的内容
{&#13;&#10;&quot;key1&quot: ...}

这当然不是我想要的。应该更像

{ "key1": "&lt;script&gt;alert(&quot;danger!&quot;)&lt;/script&gt;" }
有了这个结果,用户可以编写任何他们想要的代码,但我可以避免将其呈现为html,而只是将其显示为普通文本。有人知道如何遍历json与c# (Newtonsoft Json.NET)这样的字符串可以用AntiXssEncoder.HtmlEncode(... , ....);编码?还是我搞错了方向?编辑:

    数据是不统一的,所以反序列化成统一的对象不是一个选项。
  1. 数据可能会向公众开放,所以存储编码的数据会让我的灵魂放松。

在Json.net c#中遍历和htmlcode字符串

如果您已经拥有JSON字符串形式的数据,则可以使用JSON之类的东西将其解析为适当的对象。使用JsonConvert.DeserializeObject()(或其他任何东西,实际上有相当多的选项可供选择)。一旦它是纯对象,您就可以遍历它们并应用您想要的任何编码,然后将它们再次序列化为JSON字符串。你也可以看看这个问题和答案。

您可能采取的另一种方法是,在实际将内容插入页面DOM之前,不去管它。您可以将未编码的数据存储在数据库中,甚至可以将其发送到客户机,而不需要将其作为JSON数据进行HTML编码(当然,它需要为JSON编码,但任何序列化器都可以这样做)。您需要小心,不要以这种方式直接在页面源中生成它,但只要它是具有text/json内容类型的AJAX响应,就可以。然后在客户机上,当您决定将其插入实际的文本区域时,您需要确保将其插入为文本,而不是html。从技术上讲,这可能意味着使用jQuery的.text()而不是.html(),或者你的模板引擎或客户端数据绑定解决方案的相关方法(text:代替html:在Knockout, #:代替#=在Kendo UI,等等)

后一种方法的优点是,当发送数据时,服务器(类似于API)不需要知道或关心客户端将在哪里或如何使用数据,它只是数据。客户端可能需要HTML或Javascript上下文的不同编码,服务器不一定选择正确的编码。

如果您知道只是文本区域需要这些数据,您当然可以采用第一种(您最初的)方法,在服务器上对其进行编码,这同样很好(有些人可能会认为在这种情况下甚至更好)。

回答这个问题的问题是细节很重要。从理论上讲,你有无数种方法可以做到这一点,但有时一个好的解决方案与一个单一角色的脆弱解决方案是不同的。

这就是我想要的解决方案。我在ViewModel中添加了[AllowHtml]属性,这样我就可以从文本区发送原始html(通过ajax)。有了这个属性,我避免了MVC为防止XSS危险而提供的System.Web.HttpRequestValidationException。然后我遍历json-string,将其解析为JToken,并对字符串进行编码:

public class JsonUtils
{
    public static string HtmlEncodeJTokenStrings(string jsonString)
    {
        var reconstruct = JToken.Parse(jsonString);
        var stack = new Stack<JToken>();
        stack.Push(reconstruct);
        while (stack.Count > 0)
        {
            var item = stack.Pop();
            if (item.Type == JTokenType.String)
            {
                var valueItem = item as JValue;
                if(valueItem == null)
                    continue;
                var value = valueItem.Value<string>();
                valueItem.Value = AntiXssEncoder.HtmlEncode(value, true);
            }
            foreach (var child in item.Children())
            {
                stack.Push(child);
            }
        }
        return reconstruct.ToString();
    }
}

结果json字符串仍然是有效的,我将其存储在DB中。现在,当在视图中打印它时,我可以在JS中直接使用json中的字符串。当在另一个<textarea>中再次打开它进行编辑时,我必须解码html实体。为此,我"偷"了一些js代码(decodeHtmlEntities)从string.js;当然要加上许可证和信用说明。