Вопрос

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

Хорошо, итак, во-первых, чтобы прояснить:Я знаю, что такое поставщик членства, ролей и профилей, как реализовать свои собственные и как их настроить, а также большинство других сведений о них.
Реализация роли и поставщика профилей довольно проста, потому что большую часть времени для них требуется только простой CRUD.(Одной строки LINQ достаточно примерно для половины методов RoleProvider.)

Однако поставщик членства - это совсем другой зверь.Многие из вас могут понять, что это нарушает принцип SR (Единой ответственности), поскольку оно должно делать ВСЕ, что связано с управлением пользователями.Хотя это оставляет много места для настройки, у этого есть и свои недостатки.В Интернете нет информации о том, каково их ТОЧНОЕ ожидаемое поведение, например, когда они должны выдавать исключения или просто возвращать null и тому подобное.

Я использую этот пример реализации для справки, но он также содержит несколько противоречий.

  • Например, он использует свой собственный метод ValidateUser для проверки учетных данных в методе ChangePassword.Но ValidateUser также обновляет lastLoginDate пользователя до текущей даты.Итак, ожидает ли фреймворк, что я также установлю его у своего собственного провайдера, или это просто ошибка в примере?
  • Другой - это:метод ChangePassword генерирует исключение каждый раз при проверке нового пароля, но CreateUser никогда не генерирует исключение, он просто возвращает false .
  • И последнее, но не менее важное:он подсчитывает неверные попытки пользователя ввести пароль и блокирует их, если он превышает пороговое значение.Хотя это и хорошо, но для разблокировки пользователей требуются действия вручную.Является ли это проблемой, если мой провайдер автоматически разблокирует пользователя через определенный промежуток времени?

  • (РЕДАКТИРОВАТЬ) Чуть не забыл:метод CreateUser в примере вставляет идентификатор из параметра метода.Я на самом деле думаю, что это плохая практика, потому что я использую интерсы с автоматическим добавлением в качестве идентификаторов, поэтому вставка их из какого-либо параметра метода не является вариантом.Должен ли я просто игнорировать параметр или требовать, чтобы его значение было равно null, и выдавать исключение, если это не так?

В целом, есть ли у ASP.NET какие-либо предположения о поведении MembershipProvider?
Есть ли какая-либо документация, которая описывает, когда я должен выдавать исключение или просто возвращать null?

Я также попытался найти набор общих модульных тестов, которые давали бы некоторые рекомендации относительно ожидаемого поведения, но безуспешно, я нашел множество статей о "Модульном тестировании - это хорошо" и "Как модульно протестировать MembershipProvider", но ни одной, где были бы какие-либо реальные тесты.

Заранее спасибо всем!

Это было полезно?

Решение

Вы можете обратиться к MSDN за рекомендациями.Например, RoleProvider.RemoveUsersFromRoles содержит следующие рекомендации:

RemoveUsersFromRoles вызывается с помощью RemoveUserFromRole , RemoveUsersFromRole , RemoveUserFromRoles и методы RemoveUsersFromRoles класса Roles для удаления указанных пользователей из указанных ролей в источнике данных.Изменяются только роли для настроенного имени приложения .

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

Если какое-либо из указанных имен пользователей не связано ни с одним из указанных имен ролей для настроенного имени приложения, мы рекомендуем вашему поставщику создать Исключение ProviderException.

Если какое-либо из указанных имен пользователя равно null или представляет собой пустую строку, мы рекомендуем вашему провайдеру создать исключение.

Если какое-либо из указанных имен ролей равно null или представляет собой пустую строку, мы рекомендуем вашему поставщику создать исключение.

Если ваш источник данных поддерживает транзакции, мы рекомендуем вам включать каждую операцию удаления в транзакцию и откатывать транзакцию и создавать исключение, если какая-либо операция удаления завершается неудачно.

И RoleProvider.GetRolesForUser говорит:

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

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

Если указанное имя пользователя равно null или представляет собой пустую строку, мы рекомендуем вашему поставщику создать исключение.

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

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

Если вы используете reflector и изучите SqlMembershipProvider, вы заметите некоторые существенные различия...

Например:

  • ValidateUser обновляет дату входа в систему, потому что пользователь входит в систему, и он делает это путем вызова .CheckPassword с true для UpdateLastLoginTime.Изменение пароля вызывает тот же метод, но выдает значение false.

  • Метод CreateUser принимает ProviderUserKey, потому что SPROC также примет параметр userId.Это делается для того, чтобы обеспечить повторное использование и синхронизацию между таблицами membership и users.Как потребитель API, вы обычно не используете эту функциональность, но стек провайдера выполняет ее внутренне.

  • Что касается локаута..Это зависит только от вас.Вот в чем суть внедрения пользовательских поставщиков:получение желаемого поведения.Как я уже сказал, существует очень мало систематических требований.

Итак, это подводит нас к последней части вашего вопроса (оба абзаца ссылаются на одну и ту же проблему).:ожидаемое поведение и модульное тестирование...

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

В качестве заключительного замечания я предлагаю вам Найти и Скачать Asp.Net образцы инструментария поставщика.Он предоставляет вам рабочий исходный код для полного стека поставщиков Sql и даст вам некоторое представление о том, как реализуются "реальные" поставщики.

Запоздалые мысли:

В этот самый момент я внедряю полный стек поставщика SQLite, который на 100% совместим со стеком Sql по умолчанию.Набор тестов проверяет поведенческое соответствие между моим стеком и стеком asp.net.Если вы зайдете на мой блог через мой профиль и свяжетесь со мной, я дам вам знать, когда тесты будут завершены, и вы сможете использовать их в качестве ориентира относительно того, что именно ожидается от стека по умолчанию.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top