Perché è necessario JsonRequestBehavior?


384

Perché è Json Request Behaviornecessario

Se voglio limitare le HttpGetrichieste alla mia azione, posso decorare l'azione con l' [HttpPost]attributo

Esempio:

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

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

Perché non è [HttpPost]sufficiente?
Perché il framework ci "bug" con JsonRequestBehavior.AllowGetper ogni cosa JsonResultche abbiamo. Se voglio negare ottenere richieste, aggiungerò l' HttpPostattributo.


Molto simile a stackoverflow.com/questions/1625671/… (anche se ho trovato questo alla ricerca della mia domanda :))
Jedidja

Perché GET dovrebbe essere idempotente mentre POST non lo è. Effettuando GET -> POST, si modifica la semantica dell'interfaccia.
rism

19
Perché il tuo codice sembrerebbe troppo pulito se non dovessi aggiungere argomenti crufty ovunque.
John Shedletsky,

Risposte:


276

Per impostazione predefinita, MVC DenyGetti protegge da un attacco molto specifico che coinvolge richieste JSON per migliorare la probabilità che le implicazioni di consentire l' HTTP GETesposizione siano considerate in anticipo rispetto al loro verificarsi.

Ciò si oppone in seguito quando potrebbe essere troppo tardi.

Nota: se il metodo di azione non restituisce dati sensibili, dovrebbe essere sicuro consentire l'ottenimento.

Ulteriori letture dal mio libro Wrox ASP.NET MVC3

Per impostazione predefinita, il framework ASP.NET MVC non consente di rispondere a una richiesta GET HTTP con un payload JSON. Se è necessario inviare JSON in risposta a un GET, è necessario consentire esplicitamente il comportamento utilizzando JsonRequestBehavior.AllowGet come secondo parametro del metodo Json. Tuttavia, esiste la possibilità che un utente malintenzionato possa accedere al payload JSON attraverso un processo noto come dirottamento JSON. Non si desidera restituire informazioni riservate utilizzando JSON in una richiesta GET. Per ulteriori dettagli, consultare il post di Phil all'indirizzo http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ o questo post SO.

Haack, Phil (2011). Professional ASP.NET MVC 3 (programmatore Wrox da programmatore) (Posizioni Kindle 6014-6020). Wrox. Edizione Kindle.

Domanda StackOverflow correlata

Con la maggior parte dei browser recenti (a partire da Firefox 21, Chrome 27 o IE 10), questa non è più una vulnerabilità.


20
Ma la domanda rimane: perché [HttpPost] non è sufficiente?
gdoron sostiene Monica l'

4
Penso che sia sufficiente È necessario solo AllowGet quando si desidera consentire il passaggio dei dati come risultato di un HttpGet. DenyGet è l'impostazione predefinita, se si richiama Json (dati) con 1 parametro.
danludwig,

11
Questa è la mia domanda Perché il framework ci "bug" con il JsonRequestBehavior.AllowGetper ogni JsonResult che ho. Se voglio negare la richiesta, aggiungo l' HttpPostattributo.
gdoron sostiene Monica l'

35
Penso che sia perché non molte persone sono consapevoli di questa oscura vulnerabilità. Dici che se vuoi rifiutare la richiesta, lo farai con [HttpPost]. Tuttavia, gli autori di MVC ti offrono uno strato di protezione immediata contro questo tipo di attacco. Dal momento che è necessario fare uno sforzo per aggiungere il secondo argomento, è necessario dedicare del tempo a considerare quali dati si stanno esponendo e quanto siano sensibili.
danludwig,

11
Quindi ora ingombriamo la nostra API e aggiungiamo confusione verbale alle interfacce "RESTful" per aggirare una potenziale vulnerabilità guidata dal CLIENTE? Sembra terribile ... ma apprezzo la discussione.
Norman H,

59

Per semplificarti, puoi anche creare un 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);
    }
}

e usalo per la tua azione

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

4
Inoltre, è possibile impostare questo come filtro predefinito in RegisterGlobalFilters: filters.Add (nuovo AllowJsonGetAttribute ()). Ma poi devi rimuovere l'eccezione poiché il filtro verrà applicato per tutti i metodi di azione.
Vortex852456,

8

Per impostazione predefinita, Jsonresult "Nega get"

Supponiamo che abbiamo un metodo come di seguito

  [HttpPost]
 public JsonResult amc(){}

Per impostazione predefinita, "Nega Get".

Nel metodo seguente

public JsonResult amc(){}

Quando è necessario consentire o utilizzare get, è necessario utilizzare JsonRequestBehavior.AllowGet.

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

5

Migliorare un po 'la risposta di @Arjen de Mooij rendendo il AllowJsonGetAttribute applicabile ai controller mvc (non solo ai singoli metodi di azione):

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

Non ne hai bisogno.

Se l'azione ha l' HttpPostattributo, non è necessario preoccuparsi di impostare JsonRequestBehaviore utilizzare il sovraccarico senza di essa. C'è un sovraccarico per ogni metodo senza JsonRequestBehaviorenum. Eccoli:

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

Con 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);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.