Зачем нужен JsonRequestBehavior?


384

Зачем 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, вы меняете семантику интерфейса.
Ризм

19
Потому что ваш код выглядел бы слишком чистым, если бы вам не приходилось везде добавлять грубые аргументы.
Джон Шедлецкий

Ответы:


276

По умолчанию MVC DenyGetзащищает вас от очень специфической атаки, включающей запросы JSON, для повышения вероятности того, что последствия разрешения HTTP GETподверженности рассматриваются заранее, прежде чем они могут произойти.

Это противоположно тому, когда это может быть слишком поздно.

Примечание. Если ваш метод действия не возвращает конфиденциальные данные, тогда следует разрешить получение.

Дальнейшее чтение из моей книги по Wrox ASP.NET MVC3

По умолчанию среда ASP.NET MVC не позволяет отвечать на запрос HTTP GET с полезной нагрузкой JSON. Если вам нужно отправить JSON в ответ на GET, вам нужно явно разрешить поведение, используя JsonRequestBehavior.AllowGet в качестве второго параметра метода Json. Однако есть вероятность, что злоумышленник может получить доступ к полезной нагрузке JSON с помощью процесса, известного как JSON Hijacking. Вы не хотите возвращать конфиденциальную информацию, используя JSON в GET-запросе. Для получения дополнительной информации см. Сообщение Фила по адресу http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ или это ТАК.

Хаак, Фил (2011). Профессиональный ASP.NET MVC 3 (программист Wrox для программиста) (Kindle Locations 6014-6020). Wrox. Kindle Edition.

Связанный вопрос StackOverflow

В большинстве последних браузеров (начиная с Firefox 21, Chrome 27 или IE 10) эта уязвимость больше не существует.


20
Но остается вопрос: почему [HttpPost] недостаточно?
Гдорон поддерживает Монику

4
Я думаю, что этого достаточно. AllowGet вам нужен только тогда, когда вы хотите разрешить передачу данных в результате HttpGet. DenyGet используется по умолчанию, если вы вызываете Json (данные) с 1 параметром.
Данлудвиг

11
Это мой вопрос. Почему фреймворк «достаёт» нас из- JsonRequestBehavior.AllowGetза каждого JsonResult, который у меня есть. Если я хочу отказать в получении запроса, я добавлю HttpPostатрибут.
Гдорон поддерживает Монику

35
Я думаю, это потому, что не так много людей знают об этой неясной уязвимости. Вы говорите, что если вы хотите отклонить запрос, вы сделаете это с помощью [HttpPost]. Однако авторы MVC предоставляют вам уровень защиты из коробки от такого рода атак. Поскольку вам нужно приложить усилия для добавления второго аргумента, вам следует потратить время на то, чтобы обдумать, какие данные вы предоставляете, и насколько они чувствительны.
Данлудвиг

11
Итак, теперь мы загромождаем наш API и добавляем путаницу глаголов в интерфейсы «RESTful», чтобы обойти потенциальную уязвимость, управляемую КЛИЕНТОМ? Это кажется ужасным ... но я ценю обсуждение.
Норман Х

59

Чтобы вам было проще, вы также можете создать 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");
}

4
Кроме того, вы можете установить его в качестве фильтра по умолчанию в RegisterGlobalFilters: filters.Add (new AllowJsonGetAttribute ()). Но тогда вы должны удалить исключение, так как фильтр будет применен ко всем методам действий.
Vortex852456

8

По умолчанию Jsonresult "Запретить получить"

Предположим, если у нас есть метод, как показано ниже

  [HttpPost]
 public JsonResult amc(){}

По умолчанию это «Запретить получение».

В методе ниже

public JsonResult amc(){}

Когда вам нужно разрешить или использовать get, мы должны использовать JsonRequestBehavior.AllowGet.

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

5

Немного улучшив ответ @Arjen de Mooij, сделав 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);
    }
}

2

Тебе это не нужно.

Если у вашего действия есть 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);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.