2009-11-09 3 views
0

Чтобы разрешить пользователям и администраторам сайта для просмотра/добавлять/редактировать/удалять данные в моем приложении я решил на этом маршруте:уменьшить повторяющийся код в действиях контроллера

routes.MapRoute("ClientRoute", 
     "{account}/{controller}/{action}/{id}", 
     new { controller = "Home", action = "Index", id = "" }); 

что приводит к маршрутам, как: mvcapp.net/ 1234/контакты/добавить.

Чтобы пользователи (кроме админов) не могли получить доступ к другим данным клиента, я добавил в свои действия контроллера следующий код.

... 
    var model = repos.GetSomeData(); 
    if (User.IsInRole("Admin") == false) { 
    if (account == Profile["Client"]) 
     return View(model); 
    else 
     return View("WrongClient"); 
    } 
... 

Каков наилучший способ для этого?

РЕШЕНИЕ Я ПОШЕЛ С

public class BaseController : Controller { 
    protected override OnActionExecuting(ActionExecutingContect filterContext) { 
     if (filterContext.RouteData.Values["account"] != null) { 
     string client = filterContext.RouteData.Values["account"].ToString(); 
     if (User.IsInRole("admin") == false) { 
      if (Profile.Clients.Contains(account) == false) 
       filterContext.Result = new ViewResult() {ViewName = "WrongClient"}; 
      } 
     } 
    } 
} 

ответ

0

Я не уверен, какой профиль [«AccountNumber»] (или откуда возникает профиль), но при условии, что вы можете создать этот объект в любое время (или если оно уже создано);

Вы можете сделать следующее (место это в контроллере):

protected override void ExecuteCore() 
{ 
    var model = repos.GetSomeData(int.Parse(base.RouteData.Values["client"]))); 
    if (User.IsInRole("Admin") == false && Profile["AccountNumber"].ToString() != model.AccountNumber) 
    { 
      ViewData["Error"] = "You can't access this page"; 
      View("WrongClient").ExecuteResult(ControllerContext); 
    } 
    else 
      base.ExecuteCore(); 

} 

Вы можете поместить это все контроллеры, необходимые, или контроллеры наследуют базовый класс контроллера, который реализует эту функцию.

Идея взята из: http://forums.asp.net/t/1382514.aspx

+0

HttpContext.Profile –

+0

В этом случае я рекомендую просто проверить, соответствует ли «клиент» идентификатору пользователя (при условии, что вы используете clientid как User.Identity.Name). – Omar

+0

Ответ Paul Balmire (5-я или 6-я запись) привел меня к решение, которое я выбрал. –

1

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

Если вы обеспокоены передачей информации о пользователе в метод репозитория (как обсуждает Jabe в своем комментарии ниже), вы можете вернуть IQueryable из репозитория и запустить запрос Linq, чтобы выполнить вашу обрезку безопасности.

+0

Что делать, если вы админ и нуждаются в доступе к информации конкретного пользователя (при условии, я хочу использовать те же взгляды, созданные для пользователей)? – Omar

+0

Вы также можете передать флаг администратора методу репозитория. –

+0

Вероятно, спорный, но репозиторий не должен знать о пользователях. ИМХО это должно быть больше похоже на «дать идентификатор, получить данные». – Jabe

0

Для этого конкретного примера у Azam Sharp есть возможное решение на его blog. Я буквально наткнулся на эту статью не более пяти минут назад. Надеюсь, поможет!

+0

Глядя снова - это напрямую не касается ваших потребностей, но я все же думаю, что это можно адаптировать к тому, что вы пытаетесь сделать. –

+0

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

+0

@Robert - Вообще, я согласен. Я больше отношусь к общей идее статьи, в отличие от ее реализации. Хороший пример того, что может сделать BaseController. –

0

Действительно ли необходимо, чтобы клиент был частью маршрута, учитывая, что у вас уже есть эта информация в вашем распоряжении из профиля?

Что касается обработки этого, то уровень хранилища (как упоминалось выше) - это может стать немного сложным, поскольку это может помешать доступу к данным, необходимым внутренне для какого-либо бизнес-процесса, а также не позволить пользователю получить к нему доступ. Конечно, вы могли бы создать отдельные фильтрованные/нефильтрованные методы для этого. Кроме того, это может быть способ избежать смешивания данных клиента, когда-либо допустимый.

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

Если правила для вашего приложения очень похожи, существует несколько способов избежать повторения кода. На ум приходит пользовательский ActionFilter или пользовательский базовый класс контроллера. Если в каждой строке вашего db есть идентификатор клиента или какая-либо такая схема, другой вариант заключается в том, чтобы каждый объект домена реализовал интерфейс, отображающий этот идентификатор. Затем вы можете написать многоразовый код (методы расширения в стиле mixin и т. Д.), Который использует этот интерфейс в качестве основы для применения ваших различных правил безопасности.

+0

Не нужно иметь клиента на маршруте. Я думал, что пользователям {клиенту и администратору} будет проще. –

+0

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

+0

У моих клиентов есть 1 или более номеров счетов, и они знают их наизусть. Их жизнь, ака $$, зависит от этих чисел. Это не значит, что это не лишнее. Его просто идея не дать им всегда выбирать из списка. –

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