¿Por qué se necesita JsonRequestBehavior?

384

¿Por qué es Json Request Behaviornecesario?

Si deseo restringir las HttpGetsolicitudes a mi acción, puedo decorar la acción con el [HttpPost]atributo

Ejemplo:

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

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

¿Por qué no es [HttpPost]suficiente?
Por qué el marco nos "fastidia" con el JsonRequestBehavior.AllowGetpor todo lo JsonResultque tenemos. Si quiero negar las solicitudes de obtención, agregaré el HttpPostatributo.

gdoron está apoyando a Monica
fuente
Muy similar a stackoverflow.com/questions/1625671/… (aunque encontré este buscando mi propia pregunta :))
Jedidja
Porque se supone que GET es idempotente mientras que POST no lo es. Al hacer GETs -> POSTs, cambia la semántica de la interfaz.
rism
19
Porque su código se vería demasiado limpio si no tuviera que agregar args crudos en todas partes.
John Shedletsky

Respuestas:

276

El valor predeterminado de MVC DenyGetes protegerlo contra un ataque muy específico que involucra solicitudes JSON para mejorar la probabilidad de que las implicaciones de permitir la HTTP GETexposición se consideren antes de permitir que ocurran.

Esto se opone a después cuando podría ser demasiado tarde.

Nota: Si su método de acción no devuelve datos confidenciales, entonces debería ser seguro permitir la obtención.

Lectura adicional de mi libro Wrox ASP.NET MVC3

De manera predeterminada, el marco ASP.NET MVC no le permite responder a una solicitud HTTP GET con una carga JSON. Si necesita enviar JSON en respuesta a un GET, deberá permitir explícitamente el comportamiento utilizando JsonRequestBehavior.AllowGet como el segundo parámetro del método Json. Sin embargo, existe la posibilidad de que un usuario malintencionado pueda obtener acceso a la carga útil de JSON a través de un proceso conocido como secuestro de JSON. No desea devolver información confidencial utilizando JSON en una solicitud GET. Para obtener más detalles, consulte la publicación de Phil en http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ o esta publicación SO.

Haack, Phil (2011). ASP.NET MVC 3 profesional (programador Wrox a programador) (ubicaciones de Kindle 6014-6020). Wrox Versión Kindle.

Pregunta relacionada de StackOverflow

Con la mayoría de los navegadores recientes (comenzando con Firefox 21, Chrome 27 o IE 10), esto ya no es una vulnerabilidad.

danludwig
fuente
20
Pero la pregunta sigue siendo: ¿Por qué no es suficiente [HttpPost]?
gdoron está apoyando a Monica el
44
Creo que es suficiente Solo necesita AllowGet cuando desea permitir que los datos pasen como resultado de un HttpGet. DenyGet es el valor predeterminado, si invoca Json (datos) con 1 parámetro.
danludwig
11
Esta es mi pregunta ¿Por qué el marco nos " JsonRequestBehavior.AllowGetfastidia " con el por cada JsonResult que tengo? Si quiero negar la solicitud de obtención, agregaré el HttpPostatributo.
gdoron está apoyando a Monica el
35
Creo que es porque no mucha gente es consciente de esta oscura vulnerabilidad. Dice que si desea rechazar la solicitud, lo hará con [HttpPost]. Sin embargo, los autores de MVC le brindan una capa de protección fuera de la caja contra este tipo de ataque. Como debe hacer un esfuerzo para agregar el segundo argumento, debe tomarse ese tiempo para considerar qué datos está exponiendo y cuán sensibles son.
danludwig
11
Entonces, ¿ahora abarrotamos nuestra API y agregamos confusión verbal a las interfaces "RESTful" para evitar una posible vulnerabilidad impulsada por el CLIENTE? Esto parece terrible ... pero aprecio la discusión.
Norman H
59

Para que sea más fácil para usted, también puede crear un atributo de filtro de acción

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

y úsalo en tu acción

[AllowJsonGet]
public JsonResult MyAjaxAction()
{
    return Json("this is my test");
}
Arjen de Mooij
fuente
44
Además, puede establecer esto como filtro predeterminado en RegisterGlobalFilters: filters.Add (new AllowJsonGetAttribute ()). Pero luego debe eliminar la excepción, ya que el filtro se aplicará a todos los métodos de acción.
Vortex852456
8

Por defecto Jsonresult "Denegar obtener"

Supongamos que si tenemos un método como el siguiente

  [HttpPost]
 public JsonResult amc(){}

Por defecto es "Denegar Obtener".

En el siguiente método

public JsonResult amc(){}

Cuando necesite permitir o usar get, tenemos que usar JsonRequestBehavior.AllowGet.

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

Mejorando un poco la respuesta de @Arjen de Mooij haciendo que AllowJsonGetAttribute sea aplicable a los controladores mvc (no solo a los métodos de acción individuales):

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);
    }
}
XDS
fuente
2

No lo necesitas.

Si su acción tiene el HttpPostatributo, no necesita preocuparse por configurar JsonRequestBehaviory usar la sobrecarga sin él. Hay una sobrecarga para cada método sin la JsonRequestBehaviorenumeración. Aquí están:

Sin 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);
CodificaciónYoshi
fuente