Por que o JsonRequestBehavior é necessário?


384

Por que é Json Request Behaviornecessário?

Se eu quiser restringir os HttpGetpedidos à minha ação, eu posso decorar a ação com o [HttpPost]atributo

Exemplo:

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

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

Por que não é [HttpPost]suficiente?
Por que os quadro "bugs" dos EUA com a JsonRequestBehavior.AllowGetde todos os JsonResultque temos. Se eu quiser negar solicitações get, adicionarei o HttpPostatributo


Muito semelhante ao stackoverflow.com/questions/1625671/... (embora eu achei esta procurando minha própria pergunta :))
Jedidja

Porque GET deve ser idempotente, enquanto POST não. Ao criar GETs -> POSTs, você altera a semântica da interface.
Rism

19
Porque seu código ficaria muito limpo se você não tivesse que adicionar argumentos sujos em todos os lugares.
John Shedletsky

Respostas:


276

O MVC padroniza para DenyGetprotegê-lo contra um ataque muito específico envolvendo solicitações JSON para melhorar a probabilidade de que as implicações de permitir a HTTP GETexposição sejam consideradas antes de permitir que elas ocorram.

Isso é contra depois, quando pode ser tarde demais.

Nota: Se o seu método de ação não retornar dados confidenciais, deve ser seguro permitir o recebimento.

Outras leituras do meu livro Wrox ASP.NET MVC3

Por padrão, a estrutura do ASP.NET MVC não permite que você responda a uma solicitação HTTP GET com uma carga JSON. Se você precisar enviar JSON em resposta a um GET, precisará explicitamente permitir o comportamento usando JsonRequestBehavior.AllowGet como o segundo parâmetro para o método Json. No entanto, existe a chance de um usuário mal-intencionado obter acesso à carga útil do JSON por meio de um processo conhecido como JSON Hijacking. Você não deseja retornar informações confidenciais usando JSON em uma solicitação GET. Para obter mais detalhes, consulte a publicação de Phil em http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ ou esta publicação da SO.

Haack, Phil (2011). Profissional ASP.NET MVC 3 (programador Wrox para programador) (locais Kindle 6014-6020). Wrox. Edição Kindle.

Pergunta relacionada ao StackOverflow

Na maioria dos navegadores recentes (a partir do Firefox 21, Chrome 27 ou IE 10), isso não é mais uma vulnerabilidade.


20
Mas a questão permanece: por que o [HttpPost] não é suficiente?
gdoron está apoiando Monica

4
Eu acho que é suficiente. Você só precisa do AllowGet quando deseja permitir que os dados passem como resultado de um HttpGet. DenyGet é o padrão, se você chamar Json (data) com 1 parâmetro.
danludwig

11
Esta é a minha pergunta. Por que a estrutura "nos incomoda" com o JsonRequestBehavior.AllowGetJsonResult que eu tenho. Se eu quiser negar a solicitação de obtenção, adicionarei o HttpPostatributo
gdoron está apoiando Monica 11/11

35
Eu acho que é porque muitas pessoas não estão cientes dessa obscura vulnerabilidade. Você diz que se quiser negar a solicitação, fará isso com [HttpPost]. No entanto, os autores do MVC estão oferecendo uma camada de proteção pronta para uso contra esse tipo de ataque. Como você precisa fazer um esforço para adicionar o segundo argumento, reserve um tempo para considerar quais dados você está expondo e qual a sensibilidade deles.
danludwig

11
Portanto, agora desordenamos nossa API e adicionamos confusão de verbos às interfaces "RESTful" para contornar uma potencial vulnerabilidade orientada ao CLIENTE? Isso parece terrível ... mas eu aprecio a discussão.
Norman H

59

Para facilitar, você também pode criar um atributo actionfilter

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 use-o em sua ação

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

4
Além disso, você pode definir isso como filtro padrão em RegisterGlobalFilters: filters.Add (new AllowJsonGetAttribute ()). Mas você deve remover a exceção, pois o filtro será aplicado a todos os métodos de ação.
precisa saber é o seguinte

8

Por padrão, Jsonresult "Negar get"

Suponha que se tivermos o método abaixo

  [HttpPost]
 public JsonResult amc(){}

Por padrão, "Negar Get".

No método abaixo

public JsonResult amc(){}

Quando você precisa permitir ou usar get, temos que usar JsonRequestBehavior.AllowGet.

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

5

Melhorando um pouco a resposta de @Arjen de Mooij, tornando o AllowJsonGetAttribute aplicável aos controladores mvc (não apenas aos métodos de ação individuais):

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

Você não precisa disso.

Se sua ação tiver o HttpPostatributo, você não precisará se preocupar em definir JsonRequestBehaviore usar a sobrecarga sem ela. Há uma sobrecarga para cada método sem a JsonRequestBehaviorenumeração. Aqui estão eles:

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

Com 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);
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.