Warum wird JsonRequestBehavior benötigt?

384

Warum wird Json Request Behaviorbenötigt?

Wenn ich die HttpGetAnforderungen auf meine Aktion beschränken möchte, kann ich die Aktion mit dem [HttpPost]Attribut dekorieren

Beispiel:

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

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

Warum reicht das nicht [HttpPost]aus?
Warum das Framework uns mit dem "nervt"JsonRequestBehavior.AllowGet für jeden , JsonResultdass wir haben. Wenn ich Anfragen abrufen möchte, füge ich das HttpPostAttribut hinzu.

Gdoron unterstützt Monica
quelle
Sehr ähnlich zu stackoverflow.com/questions/1625671/… (obwohl ich diese gefunden habe, die nach meiner eigenen Frage sucht :))
Jedidja
Weil GET idempotent sein soll, POST nicht. Indem Sie GETs -> POSTs erstellen, ändern Sie die Semantik der Schnittstelle.
Risma
19
Weil Ihr Code zu sauber aussehen würde, wenn Sie nicht überall crufty args hinzufügen müssten.
John Shedletsky

Antworten:

276

MVC ist standardmäßig auf DenyGet schützt Sie vor einem sehr spezifischen Angriff mit JSON-Anforderungen, um die Wahrscheinlichkeit zu verbessern, die die Auswirkungen des Zulassens habenHTTP GET Exposition berücksichtigt werden, sie auftreten.

Dies steht im Gegensatz zu später, wenn es zu spät sein könnte.

Hinweis: Wenn Ihre Aktionsmethode keine vertraulichen Daten zurückgibt, sollte es sicher sein, das Abrufen zuzulassen.

Lesen Sie weiter aus meinem Wrox ASP.NET MVC3-Buch

Standardmäßig können Sie mit dem ASP.NET MVC-Framework nicht auf eine HTTP-GET-Anforderung mit einer JSON-Nutzlast antworten. Wenn Sie JSON als Antwort auf ein GET senden müssen, müssen Sie das Verhalten explizit zulassen, indem Sie JsonRequestBehavior.AllowGet als zweiten Parameter für die Json-Methode verwenden. Es besteht jedoch die Möglichkeit, dass ein böswilliger Benutzer über einen als JSON-Hijacking bezeichneten Prozess Zugriff auf die JSON-Nutzdaten erhält. Sie möchten keine vertraulichen Informationen mit JSON in einer GET-Anforderung zurückgeben. Weitere Informationen finden Sie in Phils Beitrag unter http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ oder in diesem SO-Beitrag.

Haack, Phil (2011). Professionelle ASP.NET MVC 3 (Wrox Programmer zu Programmer) (Kindle Locations 6014-6020). Wrox. Kindle Edition.

Verwandte StackOverflow-Frage

Bei den meisten aktuellen Browsern (beginnend mit Firefox 21, Chrome 27 oder IE 10) ist dies keine Sicherheitsanfälligkeit mehr.

danludwig
quelle
20
Die Frage bleibt jedoch: Warum reicht [HttpPost] nicht aus?
Gdoron unterstützt Monica
4
Ich denke es ist ausreichend. Sie benötigen AllowGet nur, wenn Sie zulassen möchten, dass die Daten als Ergebnis eines HttpGet übergeben werden. DenyGet ist die Standardeinstellung, wenn Sie Json (Daten) mit 1 Parameter aufrufen.
Danludwig
11
Das ist meine Frage. Warum das Framework uns mit dem JsonRequestBehavior.AllowGetfür jedes JsonResult " nervt", das ich habe. Wenn ich die Abrufanforderung ablehnen möchte, füge ich das HttpPostAttribut hinzu.
Gdoron unterstützt Monica
35
Ich denke, das liegt daran, dass sich nicht viele Menschen dieser obskuren Sicherheitslücke bewusst sind. Sie sagen, wenn Sie die Anfrage ablehnen möchten, tun Sie dies mit [HttpPost]. Die MVC-Autoren bieten Ihnen jedoch sofort Schutz vor solchen Angriffen. Da Sie sich bemühen müssen, das zweite Argument hinzuzufügen, sollten Sie sich diese Zeit nehmen, um zu überlegen, welche Daten Sie verfügbar machen und wie sensibel sie sind.
Danludwig
11
Also überladen wir jetzt unsere API und fügen "RESTful" -Schnittstellen Verbverwirrung hinzu, um eine potenzielle CLIENT-bedingte Sicherheitsanfälligkeit zu umgehen? Das scheint schrecklich ... aber ich schätze die Diskussion.
Norman H
59

Um es sich einfacher zu machen, können Sie auch ein Aktionsfilterattribut erstellen

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

und benutze es für deine Aktion

[AllowJsonGet]
public JsonResult MyAjaxAction()
{
    return Json("this is my test");
}
Arjen de Mooij
quelle
4
Darüber hinaus können Sie dies als Standardfilter in RegisterGlobalFilters festlegen: filter.Add (neues AllowJsonGetAttribute ()). Aber dann müssen Sie die Ausnahme entfernen, da der Filter für alle Aktionsmethoden angewendet wird.
Vortex852456
8

Standardmäßig Jsonresult "Deny get"

Angenommen, wir haben eine Methode wie unten

  [HttpPost]
 public JsonResult amc(){}

Standardmäßig ist es "Deny Get".

In der folgenden Methode

public JsonResult amc(){}

Wenn Sie get zulassen oder verwenden müssen, müssen wir JsonRequestBehavior.AllowGet verwenden.

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

Die Antwort von @Arjen de Mooij ein wenig verbessern, indem das AllowJsonGetAttribute auf MVC-Controller angewendet wird (nicht nur auf einzelne Aktionsmethoden):

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
quelle
2

Du brauchst es nicht.

Wenn Ihre Aktion das HttpPostAttribut hat, müssen Sie sich nicht mit dem Festlegen des Attributs befassen JsonRequestBehaviorund die Überladung ohne dieses Attribut verwenden. Für jede Methode ohne JsonRequestBehaviorAufzählung gibt es eine Überladung . Hier sind sie:

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

Mit 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);
Codierung von Yoshi
quelle