Pourquoi JsonRequestBehavior est-il nécessaire?

384

Pourquoi est-il Json Request Behaviornécessaire?

Si je veux restreindre les HttpGetdemandes à mon action, je peux décorer l'action avec l' [HttpPost]attribut

Exemple:

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

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

Pourquoi n'est-ce pas [HttpPost]suffisant?
Pourquoi le framework nous "bogue" avec JsonRequestBehavior.AllowGettout ce JsonResultque nous avons. Si je veux refuser d'obtenir des requêtes, j'ajouterai l' HttpPostattribut.

gdoron soutient Monica
la source
Très similaire à stackoverflow.com/questions/1625671/… (bien que j'ai trouvé celui-ci à la recherche de ma propre question :))
Jedidja
Parce que GET est censé être idempotent alors que POST ne l'est pas. En créant des GET -> POST, vous modifiez la sémantique de l'interface.
rism
19
Parce que votre code aurait l'air trop propre si vous n'aviez pas besoin d'ajouter des arguments cruels partout.
John Shedletsky

Réponses:

276

Par défaut, MVC DenyGetvous protège contre une attaque très spécifique impliquant des requêtes JSON afin d'améliorer la probabilité que les implications de l'autorisation d' HTTP GETexposition soient prises en compte avant de les autoriser.

Ceci est opposé à après quand il pourrait être trop tard.

Remarque: Si votre méthode d'action ne renvoie pas de données sensibles, il doit être sûr d'autoriser le get.

Lectures complémentaires de mon livre Wrox ASP.NET MVC3

Par défaut, le framework ASP.NET MVC ne vous permet pas de répondre à une requête HTTP GET avec une charge utile JSON. Si vous devez envoyer JSON en réponse à un GET, vous devrez autoriser explicitement le comportement en utilisant JsonRequestBehavior.AllowGet comme deuxième paramètre de la méthode Json. Cependant, il est possible qu'un utilisateur malveillant puisse accéder à la charge utile JSON via un processus connu sous le nom de détournement JSON. Vous ne souhaitez pas renvoyer d'informations sensibles à l'aide de JSON dans une demande GET. Pour plus de détails, consultez l'article de Phil à http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ ou cet article SO.

Haack, Phil (2011). ASP.NET MVC 3 professionnel (programmeur Wrox à programmeur) (emplacements Kindle 6014-6020). Wrox. Édition Kindle.

Question StackOverflow associée

Avec la plupart des navigateurs récents (à commencer par Firefox 21, Chrome 27 ou IE 10), ce n'est plus une vulnérabilité.

danludwig
la source
20
Mais la question demeure: pourquoi [HttpPost] n'est-il pas suffisant?
gdoron soutient Monica
4
Je pense que c'est suffisant. Vous n'avez besoin de AllowGet que lorsque vous souhaitez autoriser le passage des données à la suite d'un HttpGet. DenyGet est la valeur par défaut, si vous appelez Json (données) avec 1 paramètre.
danludwig
11
Voici ma question. Pourquoi le framework nous "bugs" avec JsonRequestBehavior.AllowGettous les JsonResult que j'ai. Si je veux refuser la demande, j'ajouterai l' HttpPostattribut.
gdoron soutient Monica
35
Je pense que c'est parce que peu de gens sont conscients de cette vulnérabilité obscure. Vous dites que si vous souhaitez refuser la demande, vous le ferez avec [HttpPost]. Cependant, les auteurs de MVC vous offrent une couche de protection prête à l'emploi contre ce type d'attaque. Étant donné que vous devez faire des efforts pour ajouter le deuxième argument, vous devez prendre le temps de réfléchir aux données que vous exposez et à leur sensibilité.
danludwig
11
Alors maintenant, nous encombrons notre API et ajoutons de la confusion verbale aux interfaces "RESTful" pour contourner une vulnérabilité potentielle liée au CLIENT? Cela semble terrible ... mais j'apprécie la discussion.
Norman H
59

Pour vous faciliter la tâche, vous pouvez également créer un attribut de filtre d'action

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

et l'utiliser sur votre action

[AllowJsonGet]
public JsonResult MyAjaxAction()
{
    return Json("this is my test");
}
Arjen de Mooij
la source
4
En outre, vous pouvez définir ce filtre par défaut dans RegisterGlobalFilters: filters.Add (new AllowJsonGetAttribute ()). Mais ensuite, vous devez supprimer l'exception car le filtre sera appliqué pour toutes les méthodes d'action.
Vortex852456
8

Par défaut Jsonresult "Deny get"

Supposons que si nous avons une méthode comme ci-dessous

  [HttpPost]
 public JsonResult amc(){}

Par défaut, il "Deny Get".

Dans la méthode ci-dessous

public JsonResult amc(){}

Lorsque vous devez autoriser get ou utiliser get, nous devons utiliser JsonRequestBehavior.AllowGet.

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

Améliorant un peu la réponse de @Arjen de Mooij en rendant le AllowJsonGetAttribute applicable aux contrôleurs mvc (pas seulement les méthodes d'action individuelles):

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
la source
2

Tu n'en a pas besoin.

Si votre action possède l' HttpPostattribut, vous n'avez pas besoin de vous soucier de la définition de JsonRequestBehavioret d'utiliser la surcharge sans celle-ci. Il y a une surcharge pour chaque méthode sans l' JsonRequestBehaviorénumération. Les voici:

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

Avec 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);
CodageYoshi
la source