Да - очень хороший вопрос. Как и @ Эндрю Купер, наша команда тоже прошла через все это.
Мы использовали следующие подходы (правильные или неправильные):
Пользовательский членство
Ни я, ни другой разработчик не поклонники встроенного поставщика членства ASP.NET. Он слишком раздут для того, что представляет собой наш сайт (простой социальный сайт, управляемый UGC). Мы создали очень простой, который делает то, что нужно нашему приложению, и ничего более. Принимая во внимание, что встроенный поставщик членства делает все, что может нужно, но, скорее всего, не будет.
Билет / Аутентификация с использованием пользовательских форм
Все в нашем приложении использует внедрение зависимостей через интерфейс (StructureMap). Это включает проверку подлинности с помощью форм. Мы создали очень тонкий интерфейс:
public interface IAuthenticationService
{
void SignIn(User user, HttpResponseBase httpResponseBase);
void SignOut();
}
Этот простой интерфейс позволяет легко макетировать / тестировать. С помощью этой реализации мы создаем пользовательский билет проверки подлинности форм, содержащий: такие вещи, как UserId и роли, которые требуются при каждом HTTP-запросе, изменяются не часто и, следовательно, не должны выбираться при каждом запросе.
Затем мы используем фильтр действий для расшифровки билета проверки подлинности форм (включая роли) и вставляем его в HttpContext.Current.User.Identity
(для которого наш объект Principal также основан на интерфейсе).
Использование [Авторизоваться] и [AdminOnly]
Мы все еще можем использовать атрибуты авторизации в MVC. И мы также создали один для каждой роли. [AdminOnly]
просто проверяет роль для текущего пользователя и выбрасывает 401 (запрещено).
Простая таблица для пользователя, простая POCO
Вся пользовательская информация хранится в одной таблице (за исключением «необязательной» информации о пользователе, такой как интересы профиля). Это сопоставлено с простым POCO (Entity Framework), который также имеет доменную логику, встроенную в объект.
Репозиторий пользователей / Сервис
Простой пользовательский репозиторий, который зависит от домена . Такие вещи, как изменение пароля, обновление профиля, получение пользователей и т. Д. Хранилище вызывает логику домена для объекта User, о котором я упоминал выше. Служба представляет собой тонкую оболочку поверх хранилища, которая разделяет отдельные методы хранилища (например, Find) на более специализированные (FindById, FindByNickname).
Домен отделен от безопасности
Наш «домен», информация о пользователе и его / ее ассоциации. Это включает в себя имя, профиль, Facebook / социальную интеграцию и т. Д.
Такие вещи, как «Логин», «Выход из системы» имеют дело с аутентификацией и такие вещи, как «User.IsInRole» имеют дело с авторизацией и, следовательно, не принадлежат домену.
Таким образом, наши контроллеры работают как с IAuthenticationService
, так и с IUserService
.
Создание профиля является прекрасным примером логики домена, которая также смешивается с логикой аутентификации.
Вот как выглядит наш:
[HttpPost]
[ActionName("Signup")]
public ActionResult Signup(SignupViewModel model)
{
if (ModelState.IsValid)
{
try
{
// Map to Domain Model.
var user = Mapper.Map<SignupViewModel, Core.Entities.Users.User>(model);
// Create salt and hash password.
user.Password = _authenticationService.SaltAndHashPassword();
// Signup User.
_userService.Save(user);
// Save Changes.
_unitOfWork.Commit();
// Forms Authenticate this user.
_authenticationService.SignIn(user, Response);
// Redirect to homepage.
return RedirectToAction("Index", "Home", new { area = "" });
}
catch (Exception exception)
{
ModelState.AddModelError("SignupError", "Sorry, an error occured during Signup. Please try again later.");
_loggingService.Error(exception);
}
}
return View(model);
}
Резюме
Вышесказанное хорошо сработало для нас. Я люблю иметь простую таблицу User, а не то раздутое безумие, которое является поставщиком членства ASP.NET. Это просто и представляет наш домен , а не его представление в ASP.NET.
Как говорится , как я уже сказал, у нас простой сайт. Если вы работаете на банковском веб-сайте, я бы позаботился о том, чтобы заново изобрести колесо.
Мой совет: сначала создайте свой домен / модель, прежде чем даже подумать об аутентификации. (конечно, это то, что DDD это все).
Затем разработайте ваши требования безопасности и выберите поставщика аутентификации (готового или обычного) соответствующим образом.
Не позволяйте ASP.NET определять, как должен создаваться ваш домен.Это ловушка, в которую попадают большинство людей (включая меня, в предыдущем проекте).
Удачи!