.Net Членство в приложении nTier - PullRequest
       16

.Net Членство в приложении nTier

10 голосов
/ 11 сентября 2009

Допустим, у меня есть приложение ASP.Net MVC, и это приложение (UI) ссылается на уровень бизнес-логики (BLL), а BLL ссылается на мой уровень доступа к данным (DAL).

Я использую провайдера нестандартного членства и ролей для авторизации.

Я пытаюсь определить, какие слои должны ссылаться на моего провайдера членства.

В MVC вы можете выполнять проверки авторизации следующим образом:

[Authorize(Roles = "SomeRoleName")]
public ActionResult Index()
{
//do something
}

И в моем BLL я, возможно, захочу проверить, есть ли пользователь и в роли:

public static bool IsRoleEditor(User user, Role userRole)
  {
   bool retValue = false;

   if (user.Application.AppID == UserRole.Application.AppID)
   {
        if (Roles.IsUserInRole("ModifyRoles"))
        {
           retValue = true;
        }


    return retValue;
   }

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

Поскольку у меня есть BLL, я избегаю использования атрибутов "[Authorize (Roles =" SomeRoleName ")]" и вместо этого вызываю функцию BLL из кода MVC, чтобы проверить, находится ли пользователь в роли? Если я сделаю это, MVC все еще будет нуждаться в ссылке на провайдера членства для аутентификации и так далее, чтобы воспользоваться преимуществами входа в систему и других элементов управления ASP, верно?

Я далеко от базы и иду в неправильном направлении?

Ответы [ 8 ]

4 голосов
/ 26 сентября 2009

На мой взгляд, это слабость членства / ролевого дизайна.

Способ, которым я мог бы обойти это, например, чтобы иметь основанную на ролях авторизацию на уровнях UI и BLL в распределенном n-уровневом приложении, состоял бы в том, чтобы предоставить сервис уровня BLL, который предоставляет соответствующие биты (GetRolesForUser и т. д.) и реализуется путем вызова RoleProvider на сервере.

Затем реализуйте пользовательский RoleProvider на клиенте, который реализуется путем вызова службы, предоставляемой BLL.

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

1 голос
/ 15 сентября 2009

Отличный вопрос, я задавал себе то же самое сегодня. Одна из идей, которые у меня были (но я не совсем уверен, что это лучший способ), - это использовать интерфейс (например, IRoleProvider), который вы можете передать в свой BLL для проверки вашего доступа.

public static bool IsRoleEditor(User user, IRoleProvider rp)
{
     return (rp.IsUserInRole(user,"ModifyRoles"));
}

При этом вы по-прежнему проверяете свой доступ в своем BLL, вы можете использовать макет в своих модульных тестах для проверки вашей логики, и вам просто нужно создать класс (или реализовать это в классе baseController) на вашем веб-сайте MVC который будет реализовывать IRoleProvider и выполнять соответствующую проверку с использованием API авторизации ASP.NET.

Надеюсь, это поможет.

0 голосов
/ 28 сентября 2009

Я думаю, что вы делаете хорошо.

Авторизация и аутентификация должны находиться на уровне сервисов, который, возможно, передается вашим контроллерам.

Если контроллер устанавливает Принципал и Идентичность, а затем вы используете их в контроллере с помощью атрибутов MVC, тогда это звучит как хорошая идея.

Было бы неплохо спрятать вашего провайдера членства MVC за интерфейсом, чтобы вы могли поменять его на провайдера членства WinForms (например) и могли бы провести модульное тестирование ваших контроллеров.

0 голосов
/ 28 сентября 2009

Называть контроллер MVC 'UI' - это совсем не то, что нужно. 'C' в MVC - это часть вашего BLL, даже если он ссылается на классы, которые you будут позвоните в BLL. Однако это не точка вашего вопроса.

Я думаю, что решил бы эту проблему, задав вопрос: «Есть ли реальное требование для 100% разделения вашего приложения« UI »и вашего« BLL »?». Если оба компонента имеют общую зависимость от поставщиков участников / ролей, пусть так и будет.

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

Я думаю, что ответ Джо выше имеет большой смысл, хотя ...

0 голосов
/ 27 сентября 2009

Вы не пропустили точку зрения MVC. MVC естественно делится на уровни. Модель (DAL), контроллер (BLL), вид (презентация). Они могут работать в разных проектах, если вам нравится, но, поскольку контроллер имеет всю бизнес-логику, вам нужен только доступ к RoleProvider.

Затем примените шаблоны, такие как хранилище, шаблоны и т. Д., Чтобы разделить их, если хотите.

Дэви

0 голосов
/ 26 сентября 2009

Почему бы не передать роли в свой BLL, чтобы не зависеть от членства. Или используйте интерфейс, предложенный MartinB.

Что произойдет в будущем, когда ваши заинтересованные лица решат использовать другую форму аутентификации и вы больше не будете работать с Role объектом?

Пример:

IsRoleEditor(User user, string[] roles)
{
  return roles.Contains("ModifyRoles");
}
0 голосов
/ 19 сентября 2009

Роль доступа обычно не должна быть в BLL. Доступ является обязанностью пользовательского интерфейса.

С учетом вышесказанного используйте интерфейс IPrinciple, как указано выше. У вас есть доступ к IPrinciple на уровне потоков.

Thread.CurrentPrincipal
0 голосов
/ 11 сентября 2009

Получите ваш объект User для реализации интерфейса IPrincipal и разбросайте его по слоям. Тогда вы все равно можете использовать встроенный атрибут [Autorize].

Хотя написано более 3 лет назад и о замке, эта статья может помочь. Он начинает вдаваться в основополагающие вещи на полпути.

HTHS
Charles

...