为啥需要 JsonRequestBehavior?

Posted

技术标签:

【中文标题】为啥需要 JsonRequestBehavior?【英文标题】:Why is JsonRequestBehavior needed?为什么需要 JsonRequestBehavior? 【发布时间】:2012-01-17 21:04:21 【问题描述】:

为什么需要Json Request Behavior

如果我想将 HttpGet 请求限制为我的操作,我可以使用 [HttpPost] 属性来装饰操作

例子:

[HttpPost]
public JsonResult Foo()

    return Json("Secrets");


// Instead of:
public JsonResult Foo()

    return Json("Secrets", JsonRequestBehavior.AllowGet);

为什么[HttpPost]不够用? 为什么框架对我们拥有的每个JsonResult 都使用JsonRequestBehavior.AllowGet 来“困扰”我们。如果我想拒绝获取请求,我将添加 HttpPost 属性。

【问题讨论】:

非常类似于***.com/questions/1625671/…(虽然我发现这个是在寻找我自己的问题:)) 因为 GET 应该是幂等的,而 POST 不是。通过 GET -> POST,您可以更改接口的语义。 因为如果您不必在各处添加粗鲁的参数,您的代码会显得过于干净。 【参考方案1】:

MVC 默认为 DenyGet 以保护您免受涉及 JSON 请求的非常具体的攻击,以提高允许 HTTP GET 暴露的含义在允许它们发生之前考虑的可能性。

这与事后可能为时已晚。

注意:如果你的 action 方法不返回敏感数据,那么允许 get 应该是安全的。

进一步阅读我的 Wrox ASP.NET MVC3 书籍

默认情况下,ASP.NET MVC 框架不允许你响应 带有 JSON 有效负载的 HTTP GET 请求。如果您需要发送 JSON 响应 GET,您需要通过以下方式明确允许该行为 使用 JsonRequestBehavior.AllowGet 作为 Json 的第二个参数 方法。但是,恶意用户有可能获得访问权限 JSON 有效负载通过称为 JSON 劫持的过程。你不 想要在 GET 请求中使用 JSON 返回敏感信息。为了 更多详细信息,请参阅 Phil 的帖子 http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ 或 this SO post.

哈克,菲尔(2011 年)。专业的 ASP.NET MVC 3(Wrox 程序员到 程序员)(Kindle 位置 6014-6020)。沃克斯。 Kindle版。

*** 相关问题

With most recents browsers (starting with Firefox 21, Chrome 27, or IE 10), this is no more a vulnerability.

【讨论】:

但问题仍然存在:为什么 [HttpPost] 还不够? 我觉得够了。仅当您希望允许数据作为 HttpGet 的结果传递时,才需要 AllowGet。如果您使用 1 个参数调用 Json(data),则默认为 DenyGet。 这是我的问题。为什么框架对我拥有的每个 JsonResult 都使用 JsonRequestBehavior.AllowGet 来“困扰”我们。如果我想拒绝获取请求,我将添加 HttpPost 属性。 我认为这是因为没有多少人意识到这个晦涩难懂的漏洞。你说如果你想拒绝请求,你会用 [HttpPost] 来做。然而,MVC 作者为您提供了针对此类攻击的开箱即用保护层。由于您需要努力添加第二个参数,因此您应该花时间考虑您要公开的数据以及它的敏感程度。 所以现在我们把 API 弄得乱七八糟,并在“RESTful”接口中添加动词混淆来绕过潜在的 CLIENT 驱动漏洞?这看起来很糟糕......但我很欣赏讨论。【参考方案2】:

为了方便您自己,您还可以创建一个 actionfilterattribute

public class AllowJsonGetAttribute : ActionFilterAttribute

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    
        var jsonResult = filterContext.Result as JsonResult;

        if (jsonResult == null)
            throw new ArgumentException("Action does not return a JsonResult, 
                                                   attribute AllowJsonGet is not allowed");

        jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;            

        base.OnResultExecuting(filterContext);
    

并在你的行动中使用它

[AllowJsonGet]
public JsonResult MyAjaxAction()

    return Json("this is my test");

【讨论】:

此外,您可以在 RegisterGlobalFilters 中将其设置为默认过滤器:filters.Add(new AllowJsonGetAttribute())。但是您必须删除异常,因为过滤器将应用于所有操作方法。【参考方案3】:

默认Jsonresult“拒绝获取”

假设我们有下面这样的方法

  [HttpPost]
 public JsonResult amc()

默认为“拒绝获取”。

在下面的方法中

public JsonResult amc()

当你需要 allowget 或使用 get 时,我们必须使用 JsonRequestBehavior.AllowGet。

public JsonResult amc()

 return Json(new Modle.JsonResponseData  Status = flag, Message = msg, html = html , JsonRequestBehavior.AllowGet);

【讨论】:

【参考方案4】:

通过制作 AllowJsonGetAttribute 适用于 mvc 控制器(不仅仅是单个操作方法):

using System.Web.Mvc;
public sealed class AllowJsonGetAttribute : ActionFilterAttribute, IActionFilter

    void IActionFilter.OnActionExecuted(ActionExecutedContext context)
    
        var jsonResult = context.Result as JsonResult;
        if (jsonResult == null) return;

        jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
    

    public override void OnResultExecuting(ResultExecutingContext filterContext)
    
        var jsonResult = filterContext.Result as JsonResult;
        if (jsonResult == null) return;

        jsonResult.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
        base.OnResultExecuting(filterContext);
    

【讨论】:

【参考方案5】:

你不需要它。

如果您的操作具有HttpPost 属性,那么您无需费心设置JsonRequestBehavior 并在没有它的情况下使用重载。没有JsonRequestBehavior 枚举的每个方法都有一个重载。他们在这里:

没有 JsonRequestBehavior

protected internal JsonResult Json(object data);
protected internal JsonResult Json(object data, string contentType);
protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding);

使用 JsonRequestBehavior

protected internal JsonResult Json(object data, JsonRequestBehavior behavior);
protected internal JsonResult Json(object data, string contentType, 
                                   JsonRequestBehavior behavior);
protected internal virtual JsonResult Json(object data, string contentType, 
    Encoding contentEncoding, JsonRequestBehavior behavior);

【讨论】:

以上是关于为啥需要 JsonRequestBehavior?的主要内容,如果未能解决你的问题,请参考以下文章

将 JsonRequestBehavior 设置为 AllowGet 时可能会泄露哪些“敏感信息”

webapi 中的错误 - 无法从“System.Web.Mvc.JsonRequestBehavior”转换为“Newtonsoft.Json.JsonSerializerSettings”

为啥我的 KendoGrid 不调用我的 MVC 控制器?

此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet。

此请求已被阻止,因为当用在 GET 请求中时,会将敏感信息透漏给第三方网站。若要允许 GET 请求,请将 JsonRequestBehavior 设置为 AllowGet。

如何格式化json数组