Dlaczego potrzebny jest JsonRequestBehavior?


384

Dlaczego jest Json Request Behaviorpotrzebny

Jeśli chcę ograniczyć HttpGetżądania do mojej akcji, mogę ozdobić akcję [HttpPost]atrybutem

Przykład:

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

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

Dlaczego nie [HttpPost]wystarcza?
Dlaczego struktura „wkurza” nas za to, JsonRequestBehavior.AllowGetco JsonResultmamy. Jeśli chcę odmówić otrzymania żądań, dodam HttpPostatrybut.


Bardzo podobny do stackoverflow.com/questions/1625671/… (chociaż znalazłem to, szukając własnego pytania :))
— Jedidja

Ponieważ GET ma być idempotentny, podczas gdy POST nie. Dokonując GET -> POST, zmieniasz semantykę interfejsu.
— Rism

19
Ponieważ twój kod wyglądałby zbyt czysto, gdybyś nie musiał wszędzie dodawać kruchych argumentów.
— John Shedletsky

Odpowiedzi:


276

MVC domyślnie DenyGetchroni Cię przed bardzo szczególnym atakiem obejmującym żądania JSON w celu zwiększenia prawdopodobieństwa, że ​​implikacje zezwolenia na HTTP GETekspozycję zostaną rozważone przed zezwoleniem na ich wystąpienie.

W przeciwieństwie do tego, kiedy może być już za późno.

Uwaga: jeśli metoda działania nie zwraca wrażliwych danych, zezwolenie na pobranie powinno być bezpieczne.

Dalsza lektura z mojej książki Wrox ASP.NET MVC3

Domyślnie środowisko ASP.NET MVC nie pozwala na odpowiedź na żądanie HTTP GET z ładunkiem JSON. Jeśli musisz wysłać JSON w odpowiedzi na GET, musisz jawnie zezwolić na zachowanie, używając JsonRequestBehavior.AllowGet jako drugiego parametru do metody Json. Istnieje jednak szansa, że ​​złośliwy użytkownik może uzyskać dostęp do ładunku JSON w procesie znanym jako porwanie JSON. Nie chcesz zwracać poufnych informacji za pomocą JSON w żądaniu GET. Aby uzyskać więcej informacji, zobacz post Phila na http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ lub ten post SO.

Haack, Phil (2011). Profesjonalny ASP.NET MVC 3 (programator Wrox do programisty) (lokalizacje Kindle 6014-6020). Wrox. Wersja Kindle.

Powiązane pytanie StackOverflow

W przypadku większości ostatnio używanych przeglądarek (począwszy od Firefox 21, Chrome 27 lub IE 10) nie jest to już luka w zabezpieczeniach.


20
Pozostaje jednak pytanie: dlaczego [HttpPost] nie jest wystarczający?
— gdoron wspiera Monikę

4
Myślę, że to wystarczy. Potrzebujesz AllowGet tylko wtedy, gdy chcesz zezwolić na przesyłanie danych w wyniku HttpGet. DenyGet jest ustawieniem domyślnym, jeśli wywołujesz Json (dane) z 1 parametrem.
— danludwig

11
To jest moje pytanie. Dlaczego framework „wkurza” nas przy JsonRequestBehavior.AllowGetkażdym JsonResult, który mam. Jeśli chcę odmówić otrzymania żądania, dodam HttpPostatrybut.
— gdoron wspiera Monikę

35
Myślę, że dzieje się tak, ponieważ niewiele osób zdaje sobie sprawę z tej niejasnej luki. Mówisz, że jeśli chcesz odrzucić prośbę, zrobisz to za pomocą [HttpPost]. Jednak autorzy MVC zapewniają natychmiastową ochronę przed tego rodzaju atakami. Ponieważ musisz podjąć wysiłek, aby dodać drugi argument, powinieneś poświęcić ten czas na zastanowienie się, jakie dane ujawniasz i jak wrażliwe.
— danludwig

11
Więc teraz zaśmiecamy nasz interfejs API i wprowadzamy zamieszanie czasownika do interfejsów „RESTful”, aby obejść potencjalną lukę spowodowaną przez KLIENTA? To wydaje się okropne ... ale doceniam dyskusję.
— Norman H

59

Aby ci to ułatwić, możesz także utworzyć atrybut filtru akcji

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

i wykorzystaj go w swojej akcji

[AllowJsonGet]
public JsonResult MyAjaxAction()
{
    return Json("this is my test");
}

4
Dodatkowo, możesz ustawić to jako domyślny filtr w RegisterGlobalFilters: filter.Add (new AllowJsonGetAttribute ()). Ale musisz usunąć wyjątek, ponieważ filtr zostanie zastosowany do wszystkich metod akcji.
— Vortex852456

8

Domyślnie Jsonresult „Deny get”

Załóżmy, że mamy metodę jak poniżej

  [HttpPost]
 public JsonResult amc(){}

Domyślnie jest to „Deny Get”.

W poniższej metodzie

public JsonResult amc(){}

Kiedy musisz zezwolić lub użyć get, musimy użyć JsonRequestBehavior.AllowGet.

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

5

Ulepszając nieco odpowiedź @Arjena de Mooij, dostosowując AllowJsonGetAttribute do kontrolerów mvc (nie tylko poszczególnych metod akcji):

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

Nie potrzebujesz tego.

Jeśli twoje działanie ma ten HttpPostatrybut, nie musisz przejmować się ustawieniem JsonRequestBehaviori użyj przeciążenia bez niego. Istnieje przeciążenie dla każdej metody bez JsonRequestBehaviorwyliczenia. Tutaj są:

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

Z 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);
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.