.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