Mengapa JsonRequestBehavior diperlukan?

384

Mengapa Json Request Behaviordibutuhkan?

Jika saya ingin membatasi HttpGetpermintaan untuk tindakan saya, saya dapat menghias tindakan dengan [HttpPost]atribut

Contoh:

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

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

Kenapa tidak [HttpPost]cukup?
Mengapa kerangka kerja "bug" kita dengan JsonRequestBehavior.AllowGetuntuk setiap JsonResultyang kita miliki. Jika saya ingin menolak mendapat permintaan saya akan menambahkan HttpPostatribut.

gdoron mendukung Monica
sumber
Sangat mirip dengan stackoverflow.com/questions/1625671/… (walaupun saya menemukan ini mencari pertanyaan saya sendiri :))
Jedidja
Karena GET seharusnya idempoten sedangkan POST tidak. Dengan membuat GET -> POST, Anda mengubah semantik antarmuka.
rism
19
Karena kode Anda akan terlihat terlalu bersih jika Anda tidak perlu menambahkan arg crufty di mana-mana.
John Shedletsky

Jawaban:

276

MVC secara default untuk DenyGetmelindungi Anda dari serangan yang sangat spesifik yang melibatkan permintaan JSON untuk meningkatkan kemungkinan implikasi mengizinkan HTTP GETpaparan dipertimbangkan sebelum memungkinkan terjadinya.

Ini ditentang setelah itu ketika mungkin sudah terlambat.

Catatan: Jika metode tindakan Anda tidak mengembalikan data sensitif, maka aman untuk mengizinkannya.

Bacaan lebih lanjut dari buku Wrox ASP.NET MVC3 saya

Secara default, kerangka kerja ASP.NET MVC tidak memungkinkan Anda untuk menanggapi permintaan HTTP GET dengan muatan JSON. Jika Anda perlu mengirim JSON sebagai respons terhadap GET, Anda harus mengizinkan perilaku secara eksplisit dengan menggunakan JsonRequestBehavior.AllowGet sebagai parameter kedua ke metode Json. Namun, ada kemungkinan pengguna jahat dapat memperoleh akses ke muatan JSON melalui proses yang dikenal sebagai Pembajakan JSON. Anda tidak ingin mengembalikan informasi sensitif menggunakan JSON dalam permintaan GET. Untuk detail lebih lanjut, lihat posting Phil di http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ atau posting SO ini.

Haack, Phil (2011). Profesional ASP.NET MVC 3 (Programmer Wrox ke Programmer) (Lokasi Kindle 6014-6020). Wrox. Edisi menyalakan.

Pertanyaan terkait StackOverflow

Dengan sebagian besar browser terbaru (dimulai dengan Firefox 21, Chrome 27, atau IE 10), ini bukan lagi sebuah kerentanan.

danludwig
sumber
20
Tetapi pertanyaannya tetap: Mengapa [HttpPost] tidak cukup?
gdoron mendukung Monica
4
Saya pikir itu sudah cukup. Anda hanya perlu AllowGet ketika Anda ingin mengizinkan data untuk lulus sebagai hasil dari HttpGet. DenyGet adalah default, jika Anda memanggil Json (data) dengan 1 parameter.
danludwig
11
Ini pertanyaan saya. Mengapa kerangka kerja "bug" kita dengan JsonRequestBehavior.AllowGetuntuk setiap JsonResult yang saya miliki. Jika saya ingin menolak mendapatkan permintaan saya akan menambahkan HttpPostatribut.
gdoron mendukung Monica
35
Saya pikir itu karena tidak banyak orang yang menyadari kerentanan yang tidak jelas ini. Anda mengatakan jika Anda ingin menolak permintaan, Anda akan melakukannya dengan [HttpPost]. Namun penulis MVC memberi Anda lapisan perlindungan di luar kotak terhadap serangan semacam ini. Karena Anda perlu berupaya untuk menambahkan argumen ke-2, Anda harus meluangkan waktu untuk mempertimbangkan data apa yang Anda paparkan, dan seberapa sensitifnya itu.
danludwig
11
Jadi sekarang kita mengacaukan API kita dan menambahkan kebingungan kata kerja ke antarmuka "RESTful" untuk menyiasati potensi kerentanan yang didorong oleh KLIEN? Ini kelihatannya mengerikan ... tapi saya menghargai diskusi ini.
Norman H
59

Untuk membuatnya lebih mudah bagi diri Anda, Anda juga bisa membuat 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);
    }
}

dan menggunakannya pada tindakan Anda

[AllowJsonGet]
public JsonResult MyAjaxAction()
{
    return Json("this is my test");
}
Arjen de Mooij
sumber
4
Selain itu, Anda dapat mengatur ini sebagai filter default di RegisterGlobalFilters: filter.Add (AllowJsonGetAttribute (baru)). Tetapi kemudian Anda harus menghapus Exception karena Filter akan diterapkan untuk semua metode tindakan.
Vortex852456
8

Secara default Jsonresult "Deny get"

Misalkan kita memiliki metode seperti di bawah ini

  [HttpPost]
 public JsonResult amc(){}

Secara default, "Tolak Get".

Dalam metode di bawah ini

public JsonResult amc(){}

Ketika Anda perlu mengizinkan atau menggunakan get, kita harus menggunakan JsonRequestBehavior.AllowGet.

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

Memperbaiki jawaban @Arjen de Mooij sedikit dengan membuat AllowJsonGetAttribute dapat digunakan untuk mvc-controllers (bukan hanya metode aksi individual):

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

Kamu tidak membutuhkannya.

Jika tindakan Anda memiliki HttpPostatribut, maka Anda tidak perlu repot-repot mengatur JsonRequestBehaviordan menggunakan kelebihan tanpa itu. Ada kelebihan untuk setiap metode tanpa JsonRequestBehaviorenum. Di sini mereka:

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

Dengan 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);
CodingYoshi
sumber