Переключение на поставщика членства в SQL из среды выполнения поставщика членства в AD

В моих функциях администратора приложения asp.net я пытаюсь объединить аутентификацию AD и авторизацию формы для создания пользователей, ролей и назначения пользователей ролям и т.д. После входа пользователя в систему с использованием аутентификации AD мне нужно переключить / назначить мой объект членства на использование AspNetSqlMembershipProvider, чтобы получить всех пользователей из объекта членства (из таблицы dbo.aspnet_Users). Как переключить провайдера во время выполнения? Я пробовал разные подходы после поиска этой проблемы, и пока что ни один из них не работает для меня. Вот несколько подходов, которые я пробовал: 1. foreach (MembershipProvider mp в Membership.Providers) {if (mp.Name == "MembershipADProvider") {Membership.Providers.Remove (MembershipADProvider ");
Пользователи MembershipUserCollection = Членство. GetAllUsers (); ddlUsers.DataSource = users; ddlUsers.DataBind ();
break;}}

Membership.Providers.Remove (MembershipADProvider "); - не работает, поскольку не поддерживается .. Кроме того, попытался очистить Membership.Providers, а затем добавить только тип AspNetSqlMembershipProvider, который также не поддерживается.

  1. Я не могу установить для Membership.Provider значение из Membership.Providers ["AspNetSqlMembershipProvider"], поскольку Membership.Provider является свойством только для чтения.

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

Пожалуйста, дайте мне знать, успешно ли кто-нибудь внедрил этот подход или вообще правдоподобен. Спасибо!


person ASPnet_user    schedule 26.08.2011    source источник


Ответы (2)


Вы бы передали явный поставщик своему коду, вместо того, чтобы напрямую зависеть от Memebership (который просто обертывает тот, который отмечен как значение по умолчанию в конфигурации). Нет необходимости менять их местами во время выполнения, подумайте, как это повлияет на безопасность потоков.

Поэтому вместо того, чтобы говорить Membership.GetAllUsers();, вы бы сделали что-то вроде (у меня нет компилятора под рукой):

public UserSerivce : IUserService
{
   private MembershipProvider provider;

   public UserService(MembershipProvider provider)
   {
       this.provider = provider;
   }

   public IEnumerable<MembershipUser> GetUsers()
   {
       return provider.GetAllUsers();
   }

   public void DoSomethingElseUseful()
   {
       ...
   }

}

А затем использовать его для конкретного провайдера:

var service = new UserService(Membership.Providers["mySqlMembershipProvider"]);
var users = service.GetUsers();

Или, если вы используете специальный код AD:

var service = new UserService(Membership.Providers["myADMembershipProvider"]);
var users = service.GetUsers();

Использование DI таким образом также помогает поддерживать тестируемость кода.

person TheCodeKing    schedule 26.08.2011
comment
Спасибо за ответ, TheCodeKing! Этот подход выглядит чище, если он работает. Я пытался ранее обратиться к конкретному провайдеру (внутри класса, а не к сервисному подходу), например - Membership.Providers [ASPNetSqlRoleProvider] .GetAllUsers (), но Provider.GetAllUsers () ожидает таких аргументов, как int pageIndex, int pageSize, out int totalRecords. Membership.GetAllUsers () вызывает базовую функцию, не имеющую аргументов. Я попытался передать такие параметры, как Provider.GetAllUsers (1, 1, out val), но это не сработало. Есть мысли по этому поводу? - person ASPnet_user; 30.08.2011
comment
Если вы посмотрите в рефлектор Membership.GetAllUsers() просто вызовет Membership.GetAllUsers(0, 2147483647, out num). Вероятно, не рекомендуется пытаться загрузить всех пользователей из соображений производительности. Лучше листать результаты. - person TheCodeKing; 30.08.2011
comment
Я искал ранее в отражателе GetAllUsers () объекта членства, и да, он вызывает Membership.GetAllUsers (0, 2147483647, out num). Мне не пришло в голову позвонить по точному коду. Теперь, когда вы снова указали на это, я попытался использовать users = Membership.Providers [AspNetSqlMembershipProvider] .GetAllUsers (0, 2147483647, out val); и это сработало! Можно ли вызывать с параметрами (0, 2147483647, out val)? Но это действительно работает! Спасибо! - person ASPnet_user; 30.08.2011

Если вам нужен список пользователей в таблице aspnet_Users, просто подключитесь к своей базе данных с System.Data.SqlClient объектами и запросите таблицу. Нет причин (о которых вы упомянули) вам нужно использовать поставщика членства для получения этих данных.

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

Изменить: я нашел несколько потенциально полезных сообщений об использовании нескольких поставщиков членства. Похоже, что общая идея состоит в том, чтобы реализовать собственный код, обрабатывающий событие Login.Authenticate на вашем Login элементе управления, и использовать Membership.Providers["ProviderName"].ValidateUser для попытки аутентификации с каждым поставщиком.

http://www.stevideter.com/2008/03/20/using-two-membership-providers-for-aspnet-logins/ http://forums.asp.net/p/1112089/1714276.aspx

person pseudocoder    schedule 26.08.2011
comment
Спасибо за ваш быстрый ответ! Я согласен, я могу использовать System.Data.SqlClient и запрашивать таблицу для заполнения списка пользователей. Но я пытался добиться этого с помощью поставщика sqlserver, чтобы сэкономить некоторую работу ... но если это вообще невозможно, то мне, возможно, придется пойти по этому пути. Кроме того, если я просто использую поставщика sqlserver для входа в систему, а также для функций администратора, я также смогу этого добиться. - person ASPnet_user; 27.08.2011
comment
Спасибо за ссылки, я думаю, что ранее искал что-то похожее на это, в котором говорится об аутентификации с использованием обоих поставщиков, что сравнительно проще. Я пробовал этот подход раньше, как MembershipProvider userProvider = Membership.Providers [ASPNetSqlRoleProvider]; userProvider.GetAllUsers (1, 1, вне val); что не сработало. - person ASPnet_user; 27.08.2011