MVC 4 WebAPI json 数组劫持

3

我有一个ApiController,其中的方法看起来像这样:

[HttpGet]
public IEnumerable<MyValue> Values()
{
     return db.MyValues.ToList();
}

它返回一个JSON数组。我使用jQuery获取结果。如何防止该数组被劫持,类似于自动嵌套等问题?

“劫持”是什么意思?你的 JSON 数据会被如何“劫持”?你试图保护自己免受什么? - Darin Dimitrov
@DarinDimitrov 我认为他指的是JavaScript数组构造函数漏洞,http://haacked.com/archive/2009/06/24/json-hijacking.aspx - tvanfosson
哦,我明白了。那么你的回答非常直接。我给你点赞。 - Darin Dimitrov
2个回答

8
您可以以通用的方式完成这项任务。
添加以下类:
public class SecureJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
    public override System.Threading.Tasks.Task WriteToStreamAsync(Type type, object value, System.IO.Stream writeStream, HttpContent content, TransportContext transportContext)
    {
        if ((typeof (IEnumerable).IsAssignableFrom(type)))
        {
            value = new {result = value};
        }
        return base.WriteToStreamAsync(type, value, writeStream, content, transportContext);
    }
}

现在,在您的WebApiConfig中,将默认的JSonMediaTypeFormatter替换为这个新的:

    config.Formatters.RemoveAt(0);
    config.Formatters.Insert(0, new SecureJsonMediaTypeFormatter());

现在您可以返回任何您想要的 IEnumerable,就像您最初所做的那样,例如:
[HttpGet]
public IEnumerable<MyValue> Values()
{
     return db.MyValues.ToList();
}

SecureJsonMediaTypeFormatter 将会拦截它,并将其封装在一个匿名对象中,在 result 属性下:

{
    "result": [
        {
            "name": "Toronto Maple Leafs",
            "league": "NHL"
        },
        {
            "name": "Montreal Canadiens",
            "league": "NHL"
        }
    ]
}

尽管我认为任何服务器端的自嵌套都会使API更加难以理解,但我还是忍不住喜欢你的做法! - rgripper
或者你可以实现一个XSRF令牌来验证请求。 - johnny 5

3
你可以简单地用一个对象包装你的结果。
   return new { values = db.MyValues.ToList() };

由于 JavaScript 对象不是有效的脚本,这可以防止结果被恶意执行,正如 Haack 在 http://haacked.com/archive/2009/06/24/json-hijacking.aspx 中所解释的那样。

我用过那个,只是觉得有一种更优雅和自动化的方式可以在不改变结果类型和添加更多噪音的情况下包装每个方法中的集合。 - rgripper

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接