Tại sao JsonRequestBehavior lại cần thiết?


384

Tại sao Json Request Behaviorcần thiết?

Nếu tôi muốn hạn chế HttpGet yêu cầu đối với hành động của mình, tôi có thể trang trí hành động bằng [HttpPost]thuộc tính

Thí dụ:

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

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

Tại sao không [HttpPost]đủ?
Tại sao khuôn khổ "lỗi" chúng tôi với JsonRequestBehavior.AllowGetmọi JsonResultthứ chúng tôi có. Nếu tôi muốn từ chối nhận yêu cầu, tôi sẽ thêm HttpPostthuộc tính.


Rất giống với stackoverflow.com/questions/1625671/ (mặc dù tôi đã tìm thấy câu hỏi này cho câu hỏi của riêng mình :))
Jedidja

Bởi vì GET được coi là idempotent trong khi POST thì không. Bằng cách thực hiện GET -> POST, bạn thay đổi ngữ nghĩa của giao diện.
nghĩa

19
Bởi vì mã của bạn sẽ trông quá sạch sẽ nếu bạn không phải thêm các đối số khủng khiếp ở mọi nơi.
John Shedletsky

Câu trả lời:


276

MVC mặc định để DenyGetbảo vệ bạn trước một cuộc tấn công rất cụ thể liên quan đến các yêu cầu JSON để cải thiện khả năng mà ý nghĩa của việc cho phép HTTP GETtiếp xúc được xem xét trước khi cho phép chúng xảy ra.

Điều này trái ngược với sau đó khi nó có thể là quá muộn.

Lưu ý: Nếu phương thức hành động của bạn không trả về dữ liệu nhạy cảm, thì nó sẽ an toàn để cho phép nhận.

Đọc thêm từ cuốn sách ASP.NET MVC3 của tôi

Theo mặc định, khung công tác ASP.NET MVC không cho phép bạn đáp ứng yêu cầu HTTP GET với tải trọng JSON. Nếu bạn cần gửi JSON để phản hồi với GET, bạn sẽ cần cho phép rõ ràng hành vi bằng cách sử dụng JsonRequestBehavior.AllowGet làm tham số thứ hai cho phương thức Json. Tuy nhiên, có khả năng người dùng độc hại có thể có quyền truy cập vào tải trọng JSON thông qua một quá trình được gọi là Tấn công JSON. Bạn không muốn trả về thông tin nhạy cảm bằng JSON trong yêu cầu GET. Để biết thêm chi tiết, xem bài đăng của Phil tại http://haacked.com/archive/2009/06/24/json-hijacking.aspx/ hoặc bài đăng SO này.

Haack, Phil (2011). ASP.NET MVC 3 chuyên nghiệp (Lập trình viên đến lập trình viên) (Kindle Locations 6014-6020). Từ điển. Phiên bản Kindle.

Câu hỏi StackOverflow liên quan

Với hầu hết các trình duyệt gần đây (bắt đầu với Firefox 21, Chrome 27 hoặc IE 10), đây không còn là một lỗ hổng.


20
Nhưng câu hỏi vẫn còn: Tại sao [httpPost] không đủ?
gdoron đang hỗ trợ Monica

4
Tôi nghĩ rằng nó là đủ. Bạn chỉ cần AllowGet khi bạn muốn cho phép dữ liệu vượt qua như là kết quả của một HTTPGet. DenyGet là mặc định, nếu bạn gọi Json (dữ liệu) với 1 tham số.
danludwig

11
Đây là câu hỏi của tôi. Tại sao khuôn khổ "lỗi" chúng tôi với JsonRequestBehavior.AllowGetmọi JsonResult mà tôi có. Nếu tôi muốn từ chối nhận yêu cầu, tôi sẽ thêm HttpPostthuộc tính.
gdoron đang hỗ trợ Monica

35
Tôi nghĩ rằng bởi vì không có nhiều người nhận thức được lỗ hổng tối nghĩa này. Bạn nói nếu bạn muốn từ chối yêu cầu, bạn sẽ thực hiện nó với [HttpPost]. Tuy nhiên, các tác giả MVC đang cung cấp cho bạn một lớp bảo vệ ngoài hộp chống lại kiểu tấn công này. Vì bạn cần nỗ lực để thêm đối số thứ 2, bạn nên dành thời gian đó để xem xét dữ liệu nào bạn đang phơi bày và mức độ nhạy cảm của nó.
danludwig

11
Vì vậy, bây giờ chúng tôi làm lộn xộn API của chúng tôi và thêm sự nhầm lẫn động từ vào các giao diện "RESTful" để khắc phục lỗ hổng điều khiển CLIENT tiềm năng? Điều này có vẻ khủng khiếp ... nhưng tôi đánh giá cao cuộc thảo luận.
Norman H

59

Để giúp bản thân dễ dàng hơn, bạn cũng có thể tạo một bộ lọc hành động

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

và sử dụng nó vào hành động của bạn

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

4
Ngoài ra, bạn có thể đặt bộ lọc này làm bộ lọc mặc định trong RegisterGlobalFilters: tests.Add (new AllowJsonGetAttribution ()). Nhưng sau đó, bạn phải xóa Ngoại lệ vì Bộ lọc sẽ được áp dụng cho tất cả các phương thức hành động.
Vortex852456

8

Theo mặc định, Jsonresult "Từ chối nhận"

Giả sử nếu chúng ta có phương pháp như dưới đây

  [HttpPost]
 public JsonResult amc(){}

Theo mặc định, nó "Từ chối Nhận".

Trong phương pháp dưới đây

public JsonResult amc(){}

Khi bạn cần cho phép hoặc sử dụng get, chúng ta phải sử dụng JsonRequestBehavior.AllowGet.

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

5

Cải thiện câu trả lời của @Arjen de Mooij một chút bằng cách làm cho AllowJsonGetAttribution áp dụng cho bộ điều khiển mvc (không chỉ các phương thức hành động riêng lẻ):

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

Bạn không cần nó.

Nếu hành động của bạn có HttpPostthuộc tính, thì bạn không cần bận tâm đến việc thiết lập JsonRequestBehaviorvà sử dụng quá tải mà không có nó. Có một quá tải cho mỗi phương thức mà không có JsonRequestBehaviorenum. Họ đây rồi:

Không có 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);

Với 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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.