为什么需要Json Request Behavior

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

示例:

>
[HttpPost]
public JsonResult Foo()
{
    return Json("Secrets");
}

// Instead of:
public JsonResult Foo()
{
    return Json("Secrets", JsonRequestBehavior.AllowGet);
}


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

评论

非常类似于stackoverflow.com/questions/1625671/…(尽管我发现这是一个搜索我自己的问题的方法:))

因为GET应该是幂等的,而POST不是。通过进行GET-> POST,可以更改接口的语义。

因为如果不必在每个地方添加繁琐的参数,您的代码看起来就会很干净。

#1 楼

MVC的默认值为DenyGet,以保护您免受涉及JSON请求的非常特定的攻击,以改善可能性,即在允许HTTP GET暴露之前先考虑允许q4312079q暴露的含义。

与之相反,这可能事后为时已晚。

注意:如果您的操作方法未返回敏感数据,则允许获取是安全的。

我的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/或此SO帖子。

Haack,Phil(2011)。专业的ASP.NET MVC 3(从Wrox编程器转换为
编程器)(Kindle位置6014-6020)。约克Kindle版。


相关的StackOverflow问题

对于最新的浏览器(从Firefox 21,Chrome 27或IE 10开始),这不再是一个漏洞。

评论


但是问题仍然存在:[HttpPost]为什么还不够?

– gdoron支持Monica
2011-12-11 14:30

我认为就足够了。仅当您要允许数据作为HttpGet的结果传递时,才需要AllowGet。如果您使用1个参数调用Json(data),则默认为DenyGet。

– danludwig
2011-12-11 14:36

这是我的问题。为什么框架为我拥有的每个JsonResult都使用JsonRequestBehavior.AllowGet来“调试”我们。如果我想拒绝获取请求,我将添加HttpPost属性。

– gdoron支持Monica
2011-12-11 14:38

我认为这是因为没有多少人意识到此隐患。您说如果要拒绝该请求,请使用[HttpPost]来完成。但是,MVC作者为您提供了一种针对此类攻击的即用型保护。由于您需要努力添加第二个参数,因此您应该花时间考虑要公开的数据及其敏感程度。

– danludwig
2011-12-11 14:42

因此,现在我们弄乱了我们的API,并向“ RESTful”接口添加了动词混淆,以解决潜在的CLIENT驱动的漏洞?这看起来很糟糕...但是我很感谢大家的讨论。

– Norman H
13年4月30日在19:34

#2 楼

为了让您自己更轻松,您还可以创建一个动作过滤器属性

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())。但是,由于过滤器将应用于所有操作方法,因此您必须删除异常。

–Vortex852456
18年1月26日在8:54



#3 楼

默认情况下,Jsonresult“拒绝获取”

如果我们有如下所示的方法

  [HttpPost]
 public JsonResult amc(){}


默认情况下为“拒绝获取”。

在以下方法中

public JsonResult amc(){}


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

public JsonResult amc()
{
 return Json(new Modle.JsonResponseData { Status = flag, Message = msg, Html = html }, JsonRequestBehavior.AllowGet);
}


#4 楼

通过使
AllowJsonGetAttribute适用于mvc控制器(而不仅仅是单个操作方法),可以稍微改善@Arjen de Mooij的答案:

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);