Я недавно создавал прототип приложения, используя WPF и Client Application Services. Я пытаюсь использовать все три функции служб клиентских приложений: проверку подлинности с помощью форм, безопасность ролей и профиль клиента. Мне удалось заставить все работать, но я чувствую, что мое решение - клочок и хочу лучшего пути.
Для обсуждения предположим следующее:
У меня есть два окна WPF:
Первое окно - моя основная форма заявки. Имеет две кнопки «Войти» и «Проверить тему»
Второе окно представляет собой форму входа в систему, которая реализует интерфейс IClientFormsAuthenticationCredentialsProvider для использования метода GetCredentials для возврата нового объекта ClientFormsAuthenticationCredentials с введенными именем пользователя и паролем.
Приложение запускается, загружается главное окно, и пользователь нажимает кнопку входа в систему. В событии нажатия кнопки вызывается System.Web.Security.Membership.ValidateUser (String.Empty, String.Empty). Это вызывает метод GetCredentials в моей форме входа в систему, который в свою очередь показывает окно входа в систему. Код в событии нажатия кнопки главного окна ожидает, пока пользователь не введет информацию в окно входа в систему.
Как только пользователь отправляет информацию для входа в систему, форма входа в систему закрывается, поток выполнения возвращается к событию щелчка входа в главное окно. Если введенные имя пользователя и пароль действительны, Thread.CurrentPrincipal имеет соответствующий принципал FormAuthentication.
Если мы вернемся к форме главного окна и нажмем кнопку «Проверить принципала потока» и проверим Thread.CurrentPrincipal для события нажатия кнопки, мы увидим, что Thread.CurrentPrincipal больше не является принципалом FormsAuthentication, а вместо этого общий принципал Windows.
В своем исследовании я нашел несколько способов справиться с этим:
Первый - вызвать AppDomain.CurrentDomain.SetThreadPrincipal (Thread.CurrentPrincipal) сразу после проверки пользователя. Это обеспечит сохранение принципала FormsAuthentication в течение всего срока службы приложения. Проблема в том, что я не могу установить его дважды. Поэтому, если я вызываю метод ClientFormsAuthenticationMembershipProvider.LogOut () и пытаюсь снова выполнить процесс входа в систему. Я получаю исключение «Основной объект по умолчанию не может быть установлен дважды».
Второй метод, и метод, который я выбрал для своего прототипа, заключается в создании класса с именем UserAuthentication. В этом классе есть статическое свойство с именем Current, которое возвращает синглтон типа UserAuthentication. В классе UserAuthentication я поддерживаю свои собственные свойства CurrentPrinipal и Original Principal, которые имеют тип IPrincipal. У меня также есть методы LogIn и LogOut, которые управляют вызовами к System.Web.Security.Membership.ValidateUser (String.Empty, String.Empty) и ClientFormsAuthenticationMembershipProvider.LogOut () и поддерживают состояние моих инкапсулированных свойств CurrentPrinipal и Original Principal.
Делая это как единое целое, я все еще могу получить доступ к функциональности IsInRole, вызвав CommonAssembly.UserAuthentication.Current.CurrentPrincipal.IsInRole ("SomeRole"). И я могу реализовать функцию профиля клиента, гарантируя, что перед вызовом Properties.Settings.Default.Save () я вызываю System.Threading.Thread.CurrentPrincipal = CommonAssembly.UserAuthentication.Current.CurrentPrincipal.
Это работает, но я чувствую, что это клочок, и в своих исследованиях я не смог найти адекватного решения. Я понимаю, что часть проблемы заключается в том, как WPF обрабатывает контекст выполнения, но я чувствую, что ДОЛЖЕН быть лучший способ.
Надеюсь, мои пояснения и примеры встроенного кода не слишком запутаны. Код, необходимый для реализации всего этого, - больше, чем я могу поместить в пост.
FYI. Я видел похожие потоки при переполнении стека, но ни один из них не дал адекватного ответа на вопрос. Я также видел примеры реализации служб клиентских приложений в Интернете, но ни один из них не использовал WPF без Silverlight.
Так есть ли лучший метод, который позволяет мне использовать Thread.CurrentPrincipal для входа в систему / выхода из системы, который устраняет необходимость в моем собственном Принципале?
Я ценю любую помощь или понимание, которое может предоставить каждый.
С уважением,
Bernie