ทำไมต้อง JsonRequestBehavior?


384

ทำไมถึงJson Request Behaviorจำเป็น?

หากฉันต้องการ จำกัดHttpGetคำขอให้ดำเนินการของฉันฉันสามารถตกแต่งแอ็คชันด้วย[HttpPost]แอตทริบิวต์

ตัวอย่าง:

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

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

ทำไมจึงไม่[HttpPost]เพียงพอ
ทำไมกรอบการทำงานของ "ข้อบกพร่อง" ที่เรามีJsonRequestBehavior.AllowGetสำหรับทุกJsonResultสิ่งที่เรามี หากฉันต้องการที่จะปฏิเสธการขอฉันจะเพิ่มHttpPostคุณสมบัติ


คล้ายกันมากกับstackoverflow.com/questions/1625671/ … (แม้ว่าฉันจะพบคำถามนี้เพื่อค้นหาคำถามของฉันเอง :))
Jedidja

เนื่องจาก GET ควรเป็น idempotent โดยที่ POST ไม่ใช่ โดยการทำให้ GETs -> POSTs คุณเปลี่ยนซีแมนติกส์ของอินเทอร์เฟซ
rism

19
เนื่องจากรหัสของคุณจะดูสะอาดเกินไปหากคุณไม่จำเป็นต้องเพิ่ม crufty args ทุกที่
John Shedletsky

คำตอบ:


276

MVC เป็นค่าเริ่มต้นเพื่อDenyGetปกป้องคุณจากการโจมตีที่เฉพาะเจาะจงมากซึ่งเกี่ยวข้องกับคำร้องขอ JSON เพื่อปรับปรุงความเป็นไปได้ที่ผลกระทบของการอนุญาตให้HTTP GETเปิดเผยจะถูกพิจารณาล่วงหน้าเพื่อให้พวกเขาเกิดขึ้น

สิ่งนี้ตรงกันข้ามกับหลังจากนั้นเมื่อมันอาจจะสายเกินไป

หมายเหตุ: หากวิธีการกระทำของคุณไม่ส่งคืนข้อมูลที่ละเอียดอ่อนควรปลอดภัยเพื่อให้ได้รับ

อ่านเพิ่มเติมจากหนังสือ Wrox ASP.NET MVC3 ของฉัน

ตามค่าเริ่มต้นกรอบงาน ASP.NET MVC ไม่อนุญาตให้คุณตอบกลับคำขอ HTTP GET พร้อมเพย์โหลด JSON หากคุณต้องการส่ง JSON เพื่อตอบสนองต่อ GET คุณจะต้องอนุญาตพฤติกรรมอย่างชัดเจนโดยใช้ JsonRequestBehavior.AllowGet เป็นพารามิเตอร์ตัวที่สองของวิธีการ Json อย่างไรก็ตามมีโอกาสที่ผู้ใช้ที่เป็นอันตรายสามารถเข้าถึง JSON payload ได้ผ่านกระบวนการที่เรียกว่า JSON Hijacking คุณไม่ต้องการส่งคืนข้อมูลที่ละเอียดอ่อนโดยใช้ JSON ในคำขอ GET สำหรับรายละเอียดเพิ่มเติมโปรดดูโพสต์ของ Phil ที่ http://haacked.com/archive/2009/06/24/json-hijacking.aspx/หรือโพสต์ SO นี้

Haack, Phil (2011) Professional ASP.NET MVC 3 (โปรแกรมเมอร์ Wrox ถึงโปรแกรมเมอร์) (ที่ตั้งจุด 6014-6020) Wrox จุด Edition.

คำถาม StackOverflow ที่เกี่ยวข้อง

ด้วยเบราว์เซอร์ที่ระลึกล่าสุด (เริ่มต้นด้วย Firefox 21, Chrome 27 หรือ IE 10) นี่ไม่ใช่ช่องโหว่อีกต่อไป


20
แต่คำถามยังคงอยู่: ทำไม [HttpPost] ไม่เพียงพอ
gdoron ให้การสนับสนุน Monica

4
ฉันคิดว่ามันเพียงพอแล้ว คุณต้องการ AllowGet เฉพาะเมื่อคุณต้องการอนุญาตให้ข้อมูลผ่านเป็นผลมาจาก HttpGet DenyGet เป็นค่าเริ่มต้นหากคุณเรียกใช้ Json (data) พร้อมพารามิเตอร์ 1 ตัว
danludwig

11
นี่คือคำถามของฉัน ทำไมเฟรมเวิร์ก "บั๊ก" เราด้วยJsonRequestBehavior.AllowGetJsonResult ทุกตัวที่ฉันมี หากฉันต้องการที่จะปฏิเสธการขอฉันจะเพิ่มHttpPostคุณสมบัติ
gdoron ให้การสนับสนุน Monica

35
ฉันคิดว่าเป็นเพราะมีคนไม่มากที่ตระหนักถึงช่องโหว่ที่คลุมเครือนี้ คุณบอกว่าถ้าคุณต้องการที่จะปฏิเสธคำขอคุณจะทำกับ [HttpPost] อย่างไรก็ตามผู้เขียน MVC ให้การปกป้องชั้นหนึ่งแก่คุณจากการโจมตีแบบนี้ เนื่องจากคุณต้องใช้ความพยายามในการเพิ่มอาร์กิวเมนต์ที่ 2 คุณควรใช้เวลาในการพิจารณาข้อมูลที่คุณเปิดเผยและความละเอียดอ่อน
danludwig

11
ดังนั้นตอนนี้เราจึงยุ่งกับ API ของเราและเพิ่มความสับสนในกริยาให้กับอินเตอร์เฟส "RESTful" เพื่อหลีกเลี่ยงช่องโหว่จากไคลเอนต์ มันดูแย่มาก ... แต่ฉันก็ยินดีที่จะพูดคุยกัน
นอร์แมน H

59

เพื่อให้ง่ายขึ้นสำหรับตัวคุณเองคุณสามารถสร้าง 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);
    }
}

และใช้กับการกระทำของคุณ

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

4
นอกจากนี้คุณสามารถตั้งค่านี้เป็นตัวกรองเริ่มต้นใน RegisterGlobalFilters: ตัวกรองเพิ่ม (ใหม่ AllowJsonGetAttribute ()) แต่คุณต้องลบข้อยกเว้นเนื่องจากตัวกรองจะถูกนำไปใช้สำหรับวิธีการกระทำทั้งหมด
Vortex852456

8

ตามค่าเริ่มต้น Jsonresult "ปฏิเสธรับ"

สมมติว่าเรามีวิธีการดังต่อไปนี้

  [HttpPost]
 public JsonResult amc(){}

โดยค่าเริ่มต้นคือ "ปฏิเสธรับ"

ในวิธีการด้านล่าง

public JsonResult amc(){}

เมื่อคุณต้องการอนุญาตหรือรับใช้เราต้องใช้ JsonRequestBehavior.AllowGet

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

5

การปรับปรุงตามคำตอบของ @Arjen de Mooij เพียงเล็กน้อยโดยการอนุญาตให้ AllowJsonGetAttribute ที่ใช้กับ mvc-controllers (ไม่ใช่แค่วิธีการกระทำเฉพาะ):

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

คุณไม่ต้องการมัน

หากการกระทำของคุณมีHttpPostคุณสมบัติคุณไม่จำเป็นต้องกังวลเกี่ยวกับการตั้งค่าJsonRequestBehaviorและใช้งานเกินพิกัดหากไม่มีการกระทำดังกล่าว มีการโอเวอร์โหลดสำหรับแต่ละวิธีโดยไม่มีJsonRequestBehavior enum ที่นี่พวกเขาคือ:

ไม่มี 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);

ด้วย 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);
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.