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

Предположим, у меня есть приложение 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 (Роли =" SomeRoleName ")]" и вместо этого вызывать функцию BLL из кода MVC, чтобы проверить, является ли пользователь в роли? Если я это сделаю, MVC по-прежнему нуждается в ссылке на поставщика членства для аутентификации и, таким образом, чтобы использовать преимущества входа и других элементов управления ASP, правильно?

Неужели я отстаю от базы и направлюсь в неправильном направлении?

Ответ 1

По моему мнению, это слабость дизайна членства/роли.

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

HTHS
Чарльз

Ответ 4

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

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

Пример:

IsRoleEditor(User user, string[] roles)
{
  return roles.Contains("ModifyRoles");
}

Ответ 5

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

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

Дэви

Ответ 6

Чтобы вызвать контроллер MVC, "UI" находится вне отметки. "C" в MVC является частью вашего BLL, даже если он ссылается на классы, которые вы бы назвали BLL. Однако это не вопрос вашего вопроса.

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

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

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

Ответ 7

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

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

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

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

Ответ 8

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

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

Thread.CurrentPrincipal