Чому потрібен 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/… (хоча я знайшов цього, шукаючи власне питання :))
Jedidja

Тому що GET повинен бути безсильним, тоді як POST - ні. Роблячи GETs -> 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. Ви не хочете повертати конфіденційну інформацію за допомогою JSON у GET-запиті. Детальніше дивіться у публікації Філа за адресою http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ або в цій публікації SO.

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

Пов'язане питання StackOverflow

У більшості оглядачів, що приймають участь (починаючи з Firefox 21, Chrome 27 або IE 10), це вже не вразливість.


20
Але питання залишається: чому [HttpPost] недостатньо?
gdoron підтримує Моніку

4
Я думаю, що це достатньо. AllowGet вам потрібен лише тоді, коли ви хочете дозволити передачу даних у результаті HttpGet. DenyGet за замовчуванням, якщо ви викликаєте Json (дані) з 1 параметром.
danludwig

11
Це моє питання. Чому фреймворк " JsonRequestBehavior.AllowGetпомиляє " нас за кожен JsonResult, який у мене є. Якщо я хочу відмовити в отриманні запиту, я додаю HttpPostатрибут.
gdoron підтримує Моніку

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

11
Отже, тепер ми захаращуємо наш API та додаємо вербову плутанину в "RESTful" інтерфейси, щоб обійти потенційну вразливість, керовану CLIENT? Це здається жахливим ... але я ціную дискусію.
Норман Н

59

Щоб полегшити себе, ви також можете створити атрибут actionfilterattribu

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 (новий 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.