2009-10-01 3 views
5

У меня есть приложение ASP.NET MVC, подобное календарю. В соответствии с примером NerdDinner, я обновляю результаты моей страницы редактирования с помощью UpdateMethod()ASP.NET MVC UpdateModel уязвим для взлома?

В моем приложении определенные события полностью настраиваются, а некоторые из них частично настраиваются. Несмотря на то, что в форме редактирования для редактирования частично настраиваемых событий доступны только эти поля, очевидно, кто-то может создать свою собственную форму с отсутствующими данными и опубликовать на моем сайте. Если они это сделают, что удержать кого-то от изменения каких-либо полей? Хуже того, что, если они попытались изменить идентификатор (первичный ключ)?

Похоже, UpdateModel() уязвим для очень простого взлома. Являются ли мои опасения законными или есть что-то, чего я не хватает?

// POST: /MyEvents/Edit/2 
[AcceptVerbs(HttpVerbs.Post), Authorize] 
public ActionResult Edit(int id, FormCollection formValues) 
{ 
    MyEvent myevent = eventRepository.GetMyEvent(id); 

    try 
    { 
     UpdateModel(myevent); 
     eventRepository.Save(); 
     return RedirectToAction("Details", new { id = myevent.MyEventId }); 
    } 
    catch 
    { 
     ModelState.AddRuleViolations(myevent.GetRuleViolations()); 
     return View(new MyEventFormViewModel(myevent)); 
    } 
} 
+0

easy/safe mode = создавать формы (в), а затем сопоставлять их с вашими объектами через Automapper. – mxmissile

ответ

9

Вам не хватает раздела «Безопасность привязки модели». Вы всегда должны включать белый список свойств, который может быть обновлен любым из ваших методов ввода пользователя.

Например, из NerdDinner:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Create([Bind(Include="Title, Address")] Dinner dinner) 
{ 

} 

или, если вы звоните UpdateModel, вы можете создать массив строк разрешенных свойств, и сделать

UpdateModel(myObject, allowedProperties); 

Вы можете заблокировать классы так что только некоторые свойства также могут быть обновлены.

[Bind(Include="MyProp1,MyProp2,MyProp3")] 
public partial class MyEntity { } 
+0

Отлично, пока у вас нет 20 или 30 элементов на экране ввода данных, тогда это станет болью =) –

+2

Вы также можете использовать черный список :) – womp

7

Ваши опасения правы. Это называется массовым назначением. Вы можете защитить свой код, пометив свой класс BindAttribute и установив Exclude/Include.

1

Есть перегрузки UpdateModel, которые берут массив свойств именования строк для обновления. Эти перегрузки будут только обновлять именованные свойства.

Могут быть другие более простые/более декларативные способы выполнения этого, я не эксперт по связыванию данных MVC.

1

Вы можете пометить поля вашей модели, которые следует игнорировать при обновлении или передать список включенных/исключенных полей, используя одну из других перегрузок UpdateModel.

4

Возможно, кому-то предприимчивому/злонамеренному отобразить поля в любом из свойств вашей модели. Существует несколько способов обойти это

Наиболее простым является использование исключений/включений свойств перегрузок UpdateModel, как уже упоминалось ранее. Недостатком этого является то, что метод принимает только строковый массив, который иногда может означать, что ваш код не синхронизируется, если вы переименовываете.

Еще один способ - использовать простой DTO, который содержит связанные поля, затем вы можете взять DTO и делать то, что хотите, с вашим объектом события, это, очевидно, добавляет еще один класс и гораздо более ручной, но дает вам гораздо больше контроль

public ActionResult(int id, EditForm form) { 
    MyEvent event = _eventRepository.GetMyEvent(id); 
    event.Name = form.Name; //etc; 
    if (User.IsInRole("Organiser")) { 
     event.Date = form.Date; 
    } 
    return ... 
} 

Другим способом может быть с помощью модели связующего клиента для вашего класса MyEvent который только связывает ваше нужное поле, вероятно, слишком много, хотя.

Смежные вопросы