Пошаговое руководство. Использование служб клиентских приложений
Обновлен: Июль 2008
В этом разделе описывается, как создать приложение Windows, использующее клиентские службы приложений для проверки подлинности пользователей и получения пользовательских ролей и параметров.
В данном пошаговом руководстве нужно выполнить следующие задачи:
Создать приложение Windows Forms и использовать конструктор проектов Visual Studio для включения и настройки клиентских служб приложений.
Создать простое приложение веб-службы ASP.NET для размещения служб приложений и тестирования конфигурации клиента.
Добавить в приложение проверку подлинности в формах. Сначала для тестирования службы будет использоваться указанное в коде имя пользователя и пароль. Затем мы добавим форму входа, указав ее в качестве поставщика учетных данных в конфигурации приложения.
Добавить поддержку ролей: в приложении будет отображаться кнопка только для пользователей с ролью "руководитель".
Получить доступ к веб-параметрам. Сначала будут загружены веб-параметры для прошедшего проверку пользователя на странице Параметры конструктора проектов. Затем с помощью конструктора Windows Forms с веб-параметром будет связано текстовое поле. И наконец, измененное значение будет сохранено на сервере.
Внедрить выход. В форму будет добавлена функция выхода и вызов метода выхода.
Включить автономный режим. В форме будет предусмотрен флажок, чтобы пользователи могли указать состояние подключения. Это значение будет использовано для того, чтобы поставщики клиентской службы приложений использовали данные, кэшированные в локальной системе, вместо доступа к веб-службам. После возврата в оперативный режим будет выполняться повторная проверка подлинности текущего пользователя.
Обязательные компоненты
Для выполнения инструкций данного пошагового руководства необходимы следующие компоненты:
- Visual Studio 2008.
Создание клиентского приложения
Для начала следует создать проект Windows Forms. Проекты Windows Forms используются в данном случае, поскольку с ними знакомо больше людей, но процесс аналогичен работе с проектами Windows Presentation Foundation (WPF).
Для создания клиентского приложения и включения клиентских служб приложений выполните следующие действия.
В Visual Studio выберите Файл | Создать | Проект.
В окне Создать проект в области Типы проектов разверните узел Visual Basic или Visual C# и выберите тип проекта Windows.
Убедитесь, что выбран параметр .NET Framework 3.5, затем выберите шаблон Приложение Windows Forms.
Измените имя проекта на ClientAppServicesDemoи нажмите кнопку ОК.
Новый проект Windows Forms откроется в Visual Studio.
В меню Проект выберите Свойства ClientAppServicesDemo.
Появится конструктор проектов.
На вкладке Службы выберите Включить клиентские службы приложений.
Убедитесь, что выбран параметр Использовать проверку подлинности в формах затем установите для параметров Расположение службы проверки подлинности, Расположение службы ролей и Расположение службы веб-параметров значение https://localhost:55555/AppServices.
В Visual Basic на вкладке Приложение установите параметру Режим проверки подлинности значение Определяется приложением.
Конструктор сохранит указанные параметры в файле app.config приложения.
На этом этапе приложение настроено для доступа ко всем трем службам на одном и том же узле. В следующем разделе мы создадим узел в качестве простого приложения веб-служб, что позволит протестировать конфигурацию клиента.
Создание узла служб приложений
В этом разделе будет показано, как создать простое приложение веб-служб, которое получает доступ к данным пользователя из файла локальной базы данных SQL Server Compact 3.5. Затем будет заполнена база данных с помощью Средство администрирования веб-узла ASP.NET. Данная простая конфигурация позволяет быстро протестировать свое клиентское приложение. В качестве альтернативы можно сконфигурировать узел веб-службы для доступа к данным пользователя из полной базы данных SQL Server или через пользовательские классы MembershipProvider и RoleProvider. Дополнительные сведения см. в разделе Создание и настройка базы данных служб приложения для SQL Server.
В следующей процедуре будет создана и настроена веб-служба AppServices.
Для создания и настройки узла служб приложений выполните следующие действия.
В Обозревателе решений выберите решение ClientAppServicesDemo, затем в меню Файл выберите Добавить | Новый проект.
В окне Добавить новый проект в области Типы проектов разверните узел Visual Basic или Visual C# и выберите тип проекта Веб.
Убедитесь, что выбран параметр .NET Framework 3.5, затем выберите шаблон Приложение веб-службы ASP.NET.
Измените имя проекта на AppServicesи нажмите кнопку ОК.
В решение добавляется новый проект приложения веб-службы ASP.NET, а в редакторе появляется файл Service1.asmx.vb или Service1.asmx.cs.
Примечание. Файл Service1.asmx.vb или Service1.asmx.cs не используется в данном примере. Если необходимо поддерживать среду работы незагруженной, можно закрыть его и удалить из Обозревателя решений.
В Обозревателе решений выберите проект AppServices, затем в меню Проект выберите Свойства AppServices.
Появится конструктор проектов.
На вкладке Веб установите флажок Использовать Visual Studio Development Server.
Выберите Определенный порт, укажите значение 55555, затем установите параметр Виртуальный путь равным /AppServices.
Сохраните все файлы.
В Обозревателе решений откройте файл Web.config и найдите тег <system.web>.
Перед тегом <system.web> добавьте следующую строку.
Элементы authenticationService, profileService и roleService в этом коде включают и настраивают службы приложения. В целях тестирования атрибут requireSSL элемента authenticationService имеет значение "false". Атрибуты readAccessProperties и writeAccessProperties элемента profileService указывают, что свойство WebSettingsTestText доступно для чтения и записи.
Примечание. В рабочем коде всегда следует получать доступ к службе проверки подлинности с помощью безопасного уровня SSL (по протоколу HTTPS). Дополнительные сведения о настройке SSL см. в разделе Настройка SSL (Руководство пользователя IIS 6.0).
<system.web.extensions> <scripting> <webServices> <authenticationService enabled="true" requireSSL = "false"/> <profileService enabled="true" readAccessProperties="WebSettingsTestText" writeAccessProperties="WebSettingsTestText" /> <roleService enabled="true"/> </webServices> </scripting> </system.web.extensions>
Добавьте следующий код после открывающего тега <system.web>, чтобы этот код находится внутри элемента <system.web>.
Элемент profile настраивает один веб-параметр WebSettingsTestText.
<profile enabled="true" > <properties> <add name="WebSettingsTestText" type="string" readOnly="false" defaultValue="DefaultText" serializeAs="String" allowAnonymous="false" /> </properties> </profile>
В следующей процедуре для конфигурирования службы и заполнения файла локальной базы данных используется средство администрирования веб-узла ASP.NET. Добавляются два пользователя с именами сотрудник и менеджер, принадлежащие двум ролям с одинаковыми именами. Пароли пользователя employee! и manager!, соответственно.
Настройка членства и ролей
В Обозревателе решений выберите проект AppServices, а в меню Проект — Настройки ASP.NET.
Появляется средство администрирования веб-узла ASP.NET.
На вкладке Безопасность щелкните Использовать Мастер настройки безопасности для пошаговой настройки безопасности.
Появляется Мастер настройки безопасности и отображается шаг Добро пожаловать.
Нажмите кнопку Далее.
Отображается шаг Выбор способа доступа.
Выбрать Из Интернета. Это позволяет настроить службу для использования проверки подлинности с помощью форм вместо проверки подлинности Windows.
Нажмите кнопку Далее дважды.
Отображается шаг Определение ролей.
Выберите Включить роли для данного веб-узла.
Нажмите кнопку Далее. Отображается форма Создать новую роль.
В текстовом поле Имя новой роли введите менеджер и нажмите кнопку Добавить роль.
Таблица Существующие роли отображается с заданным значением.
В текстовом поле Имя новой роли замените менеджер на сотрудник и нажмите кнопку Добавить роль.
В таблице Существующие роли отображается новое значение.
Нажмите кнопку Далее.
Отображается шаг Добавление новых пользователей.
В форме Создать пользователя задайте следующие значения.
Имя пользователя
менеджер
Пароль
manager!
Подтверждение пароля
manager!
Электронная почта
manager@contoso.com
Контрольный вопрос
менеджер
Ответ на контрольный вопрос
менеджер
Нажмите кнопку Создать пользователя.
Отображается сообщение об успехе.
Примечание. В форму необходимо ввести значения Электронная почта, Контрольный вопрос и Ответ на контрольный вопрос, однако они не используются в данном примере.
Нажмите кнопку Продолжить.
Форма Создать пользователя отображается вновь.
В форме Создать пользователя задайте следующие значения.
Имя пользователя
сотрудник
Пароль
employee!
Подтверждение пароля
employee!
Электронная почта
employee@contoso.com
Контрольный вопрос
Сотрудник
Ответ на контрольный вопрос
сотрудник
Нажмите кнопку Создать пользователя.
Отображается сообщение об успехе.
Нажмите кнопку Готово.
Средство администрирования веб-узла отображается снова.
Выбрать Пользователи "руководители".
Отображается список пользователей.
Для пользователя сотрудник щелкните Изменить роли и выберите роль сотрудник.
Для пользователя менеджер щелкните Изменить роли и выберите роль менеджер.
Закройте окно обозревателя, содержащее Средство администрирования веб-узла.
При отображении окна сообщений, спрашивающего, нужно ли повторно загружать измененный файл Web.config, нажмите Да.
Теперь настройка веб-службы завершена. Можно нажать клавишу F5 для запуска клиентского приложения; при этом одновременно с приложением будет автоматически запущен сервер ASP.NET Development Server. Сервер продолжит работу после выхода из приложения, но будет перезапущен при перезапуске приложения. Это позволит обнаружить все изменения файла Web.config.
Чтобы вручную остановить сервер, щелкните правой кнопкой мыши значок сервера ASP.NET Development Server в области уведомлений панели задач и выберите Остановить. Это может пригодиться в некоторых случаях, чтобы убедиться в том, что система перезапущена.
Добавление проверки подлинности с помощью форм
В следующей процедуре в основную форму добавляется код, который пытается проверить подлинность пользователя и отказывает в доступе, если пользователь вводит неверные учетные данные. Для тестирования службы будет использоваться указанное в коде имя пользователя и пароль.
Для проверки пользователя в коде приложения выполните следующие действия.
В Обозревателе решений в проекте ClientAppServicesDemo добавьте ссылку на сборку System.Web.
Выберите файл Form1 и выберите Вид | Код в главном меню Visual Studio.
В редакторе кода добавьте следующие операторы в начало файла Form1.
Imports System.Net Imports System.Threading Imports System.Web.ClientServices Imports System.Web.ClientServices.Providers Imports System.Web.Security
using System.Net; using System.Threading; using System.Web.ClientServices; using System.Web.ClientServices.Providers; using System.Web.Security;
В Обозревателе решений дважды щелкните Form1, чтобы открыть конструктор.
В конструкторе дважды щелкните поверхность формы для создания обработчика событий Form.Load с именем Form1_Load.
Откроется редактор кода с курсором на методе Form1_Load.
Добавьте следующий код в метод Form1_Load.
Это запретит доступ не прошедшим проверку пользователям путем закрытия приложения. Также можно разрешить пользователям, не прошедшим проверку, доступ к форме, но запретить доступ к определенным функциям. Обычно не следует вносить в код имя пользователя и пароль, но это полезно для тестирования. В следующем разделе мы заменим этот код на более надежный, который включает окно входа и обработку ошибок.
Обратите внимание, что метод static Membership.ValidateUser находится в .NET Framework, версия 2.0. Этот метод делегирует свою работу настроенному поставщику проверки подлинности и возвращает значение true при успешной проверке. В коде приложения не требуется непосредственной ссылки на поставщика проверки подлинности.
If Not Membership.ValidateUser("manager", "manager!") Then MessageBox.Show("Unable to authenticate.", "Not logged in", _ MessageBoxButtons.OK, MessageBoxIcon.Error) Application.Exit() End If
if (!Membership.ValidateUser("manager", "manager!")) { MessageBox.Show("Unable to authenticate.", "Not logged in", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); }
Теперь можно нажать клавишу F5 для запуска приложения и на экране появится форма, поскольку вводится правильное имя пользователя и пароль.
Примечание. |
---|
Если не удается запустить приложение, остановите сервер ASP.NET Development Server. После перезапуска сервера убедитесь, что установлен номер порта 55555. |
Чтобы увидеть сообщение об ошибке, измените параметры ValidateUser. Например, замените второй параметр "manager!" неверным паролем, таким как "MANAGER".
Добавление формы входа в качестве поставщика учетных данных
Можно получить учетные данные пользователей в коде приложения и передать их методу ValidateUser. Однако рекомендуется отделять код, получающий учетные данные, от кода приложения: так удобнее вносить изменения.
В следующей процедуре мы настроим приложение на использование поставщика учетных данных, затем изменим вызов метода ValidateUser для передачи Empty для обоих параметров. Из-за пустых строк метод ValidateUser вызовет метод GetCredentials настроенного поставщика учетных данных.
Для настройки приложения на использование поставщика учетных данных выполните следующие действия.
В Обозревателе решений выберите проект ClientAppServicesDemo, затем в меню Проект выберите Свойства ClientAppServicesDemo.
Появится конструктор проектов.
На вкладке Службы установите параметру Optional: Credential provider следующее значение. Это значение указывает имя типа сборки.
ClientAppServicesDemo.Login, ClientAppServicesDemo
В файле кода Form1 замените код в методе Form1_Load следующим кодом.
Этот код отображает приветствие и затем вызывает метод ValidateUsingCredentialsProvider, который мы добавим на следующем этапе. Если пользователь не прошел проверку, метод ValidateUsingCredentialsProvider возвращает значение false и возврат метода Form1_Load. Это препятствует выполнению любого дополнительного кода перед выходом приложения. Отображение приветствия позволяет точно установить, что приложение было перезапущено. После реализации выхода (см. ниже) мы добавим код перезапуска приложения.
MessageBox.Show("Welcome to the Client Application Services Demo.", _ "Welcome!") If Not ValidateUsingCredentialsProvider() Then Return
MessageBox.Show("Welcome to the Client Application Services Demo.", "Welcome!"); if (!ValidateUsingCredentialsProvider()) return;
Добавьте следующий метод после метода Form1_Load.
Этот метод передает пустые строки методу static Membership.ValidateUser, который открывает окно входа. Если служба проверки подлинности недоступна, метод ValidateUser создает WebException. В этом случае метод ValidateUsingCredentialsProvider отображает предупреждающее сообщение и запрашивает, хочет ли пользователь повторить попытку в автономном режиме. Для этого необходима функция Сохранить хэш пароля в локальной системе для входа в автономном режиме, описанная в разделе Практическое руководство. Настройка служб клиентских приложений. Эта функция включена по умолчанию для новых проектов.
Если пользователь не проходит проверку, метод ValidateUsingCredentialsProvider отображает сообщение об ошибке и завершает работу приложения. И наконец метод возвращает результат попытки проверки.
Private Function ValidateUsingCredentialsProvider() As Boolean Dim isAuthorized As Boolean = False Try ' Call ValidateUser with empty strings in order to display the ' login dialog box configured as a credentials provider. isAuthorized = Membership.ValidateUser( _ String.Empty, String.Empty) Catch ex As System.Net.WebException If DialogResult.OK = MessageBox.Show( _ "Unable to access the authentication service." & _ Environment.NewLine & "Attempt login in offline mode?", _ "Warning", MessageBoxButtons.OKCancel, _ MessageBoxIcon.Warning) Then ConnectivityStatus.IsOffline = True isAuthorized = Membership.ValidateUser( _ String.Empty, String.Empty) End If End Try If Not isAuthorized Then MessageBox.Show("Unable to authenticate.", "Not logged in", _ MessageBoxButtons.OK, MessageBoxIcon.Error) Application.Exit() End If Return isAuthorized End Function
private bool ValidateUsingCredentialsProvider() { bool isAuthorized = false; try { // Call ValidateUser with empty strings in order to display the // login dialog box configured as a credentials provider. isAuthorized = Membership.ValidateUser( String.Empty, String.Empty); } catch (System.Net.WebException) { if (DialogResult.OK == MessageBox.Show( "Unable to access the authentication service." + Environment.NewLine + "Attempt login in offline mode?", "Warning", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning)) { ConnectivityStatus.IsOffline = true; isAuthorized = Membership.ValidateUser( String.Empty, String.Empty); } } if (!isAuthorized) { MessageBox.Show("Unable to authenticate.", "Not logged in", MessageBoxButtons.OK, MessageBoxIcon.Error); Application.Exit(); } return isAuthorized; }
Создание формы входа
Поставщик учетных данных — это класс, реализующий интерфейс IClientFormsAuthenticationCredentialsProvider. В этом интерфейсе используется метод GetCredentials, возвращающий объект ClientFormsAuthenticationCredentials. Следующая процедура описывает создание окна входа с реализацией GetCredentials для отображения окна и возврата учетных данных, введенных пользователем.
Отдельные процедуры предназначены для Visual Basic и для C#, поскольку в Visual Basic есть шаблон Форма входа. Это позволяет сократить время кодирования.
Для создания диалогового окна входа в качестве поставщика учетных данных в Visual Basic выполните следующие действия.
В Обозревателе решений выберите проект ClientAppServicesDemo, затем в меню Проект выберите Добавить новый элемент.
В диалоговом окне Добавить новый элемент выберите шаблон Форма входа, измените Имя на Login.vb и нажмите кнопку Добавить.
Окно входа откроется в конструкторе Windows Forms.
В конструкторе выберите кнопку ОК и в окне Свойства установите свойству DialogResult значение OK.
В конструкторе добавьте элемент управления CheckBox под текстовым полем Пароль.
В окне Свойства укажите свойству (Имя) значение rememberMeCheckBox, а свойству Текст — значение &Запомнить меня.
В главном меню Visual Studio выберите Вид | Код.
В редакторе кода добавьте следующий код в начало файла.
Imports System.Web.ClientServices.Providers
Измените подпись класса, чтобы класс реализовал интерфейс IClientFormsAuthenticationCredentialsProvider.
Public Class Login Implements IClientFormsAuthenticationCredentialsProvider
Убедитесь, что курсор находится ниже IClientformsAuthenticationCredentialsProvider, затем нажмите клавишу ВВОД для создания метода GetCredentials.
Найдите реализацию GetCredentials и замените ее следующим кодом.
Public Function GetCredentials() As _ ClientFormsAuthenticationCredentials Implements _ IClientFormsAuthenticationCredentialsProvider.GetCredentials If Me.ShowDialog() = DialogResult.OK Then Return New ClientFormsAuthenticationCredentials( _ UsernameTextBox.Text, PasswordTextBox.Text, _ rememberMeCheckBox.Checked) Else Return Nothing End If End Function
Следующая процедура C# содержит полный текст кода для простого диалогового окна входа в систему. Внешний вид этого окна несколько простоват, но важная часть — это реализация GetCredentials.
Для создания диалогового окна входа в качестве поставщика учетных данных в C# выполните следующие действия.
В Обозревателе решений выберите проект ClientAppServicesDemo, затем в меню Проект выберите Добавить класс.
В диалоговом окне Добавить новый элемент измените Имя на Login.cs и нажмите кнопку Добавить.
В редакторе кода откроется файл Login.cs.
Замените код по умолчанию следующим кодом.
using System.Windows.Forms; using System.Web.ClientServices.Providers; namespace ClientAppServicesDemo { class Login : Form, IClientFormsAuthenticationCredentialsProvider { private TextBox usernameTextBox; private TextBox passwordTextBox; private CheckBox rememberMeCheckBox; private Button OK; private Button cancel; private Label label1; private Label label2; public ClientFormsAuthenticationCredentials GetCredentials() { if (this.ShowDialog() == DialogResult.OK) { return new ClientFormsAuthenticationCredentials( usernameTextBox.Text, passwordTextBox.Text, rememberMeCheckBox.Checked); } else { return null; } } public Login() { InitializeComponent(); } private void CloseForm(object sender, System.EventArgs e) { this.Close(); } private void InitializeComponent() { this.label1 = new System.Windows.Forms.Label(); this.usernameTextBox = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.passwordTextBox = new System.Windows.Forms.TextBox(); this.rememberMeCheckBox = new System.Windows.Forms.CheckBox(); this.OK = new System.Windows.Forms.Button(); this.cancel = new System.Windows.Forms.Button(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(13, 13); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(58, 13); this.label1.TabIndex = 0; this.label1.Text = "&User name"; // // usernameTextBox // this.usernameTextBox.Location = new System.Drawing.Point(13, 30); this.usernameTextBox.Name = "usernameTextBox"; this.usernameTextBox.Size = new System.Drawing.Size(157, 20); this.usernameTextBox.TabIndex = 1; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(13, 57); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(53, 13); this.label2.TabIndex = 2; this.label2.Text = "&Password"; // // passwordTextBox // this.passwordTextBox.Location = new System.Drawing.Point(13, 74); this.passwordTextBox.Name = "passwordTextBox"; this.passwordTextBox.PasswordChar = '*'; this.passwordTextBox.Size = new System.Drawing.Size(157, 20); this.passwordTextBox.TabIndex = 3; // // rememberMeCheckBox // this.rememberMeCheckBox.AutoSize = true; this.rememberMeCheckBox.Location = new System.Drawing.Point(13, 101); this.rememberMeCheckBox.Name = "rememberMeCheckBox"; this.rememberMeCheckBox.Size = new System.Drawing.Size(94, 17); this.rememberMeCheckBox.TabIndex = 4; this.rememberMeCheckBox.Text = "&Remember me"; this.rememberMeCheckBox.UseVisualStyleBackColor = true; // // OK // this.OK.DialogResult = System.Windows.Forms.DialogResult.OK; this.OK.Location = new System.Drawing.Point(13, 125); this.OK.Name = "OK"; this.OK.Size = new System.Drawing.Size(75, 23); this.OK.TabIndex = 5; this.OK.Text = "&OK"; this.OK.UseVisualStyleBackColor = true; // // cancel // this.cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.cancel.Location = new System.Drawing.Point(95, 125); this.cancel.Name = "cancel"; this.cancel.Size = new System.Drawing.Size(75, 23); this.cancel.TabIndex = 6; this.cancel.Text = "&Cancel"; this.cancel.UseVisualStyleBackColor = true; // // Login // this.AcceptButton = this.OK; this.CancelButton = this.cancel; this.ClientSize = new System.Drawing.Size(187, 168); this.Controls.Add(this.cancel); this.Controls.Add(this.OK); this.Controls.Add(this.rememberMeCheckBox); this.Controls.Add(this.passwordTextBox); this.Controls.Add(this.label2); this.Controls.Add(this.usernameTextBox); this.Controls.Add(this.label1); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "Login"; this.Text = "Login"; this.ResumeLayout(false); this.PerformLayout(); } } }
Теперь можно запустить приложение, при этом появится окно входа. Для проверки этого кода попробуйте вводить различные учетные данные, верные и неверные, и убедитесь, что доступ к форме предоставляется только для допустимых учетных данных. Допустимые имена пользователей — сотрудник и менеджер с паролями employee! и manager!, соответственно.
Примечание. |
---|
Не устанавливайте флажок Запомнить меня на этом этапе, иначе вы не сможете войти в систему с данными другого пользователя до реализации процедуры входа, которая далее описана в данном пошаговом руководстве. |
Добавление поддержки ролей
В следующей процедуре в форму добавляется кнопка, которая будет отображаться только для пользователей с ролью "руководитель".
Для изменения пользовательского интерфейса на основе роли пользователя выполните следующие действия.
В Обозревателе решений в проекте ClientAppServicesDemo выберите форму Form1 и выберите в главном меню Visual Studio Вид | Конструктор.
В конструкторе добавьте элемент управления Button из панели элементов.
В окне Свойства установите следующие свойства для кнопки.
Свойство
Значение
(Имя)
managerOnlyButton
Текст
&Задача руководителя
Видимость
False
В редакторе кода для формы Form1 добавьте следующий код в конец метода Form1_Load.
Этот код вызывает метод DisplayButtonForManagerRole, который мы добавим на следующем этапе.
DisplayButtonForManagerRole()
DisplayButtonForManagerRole();
Добавьте в конец класса Form1 следующий метод.
Этот метод вызывает метод IsInRole из IPrincipal, возвращаемый свойством static Thread.CurrentPrincipal. Для приложений, настроенных для использования клиентских служб приложений, это свойство возвращает значение ClientRolePrincipal. Поскольку этот класс реализует интерфейс IPrincipal, нет необходимости ссылаться на него явным образом.
Если пользователь имеет роль "руководитель", то метод DisplayButtonForManagerRole устанавливает свойству Visible элемента управления managerOnlyButton значение true. Этот метод также отображает сообщение об ошибке при возникновении WebException, указывающего на недоступность службы ролей.
Примечание. Метод IsInRole всегда возвращает false, если имя пользователя больше не действует. Этого не произойдет, если приложение вызывает метод IsInRole однократно вскоре после проверки подлинности, как показано в примере кода для этого пошагового руководства. Если приложению нужно извлечь роли пользователя в другое время, можно добавить код для повторной проверки пользователей, если их имена пользователей не действуют. Если все действующий пользователи назначены ролям, для определения того, действует ли имя пользователя, можно вызвать метод ClientRoleProvider.GetRolesForUser. Если ни одна роль не возвращается, имя пользователя истекло и недействительно. Пример такой функциональности см. в методе GetRolesForUser. Эта функциональность требуется только в том случае, если в конфигурации приложения был выбран параметр Требовать повторного входа пользователей при истечении "cookie" на сервере. Дополнительные сведения см. в разделе Практическое руководство. Настройка служб клиентских приложений.
Private Sub DisplayButtonForManagerRole() Try If Thread.CurrentPrincipal.IsInRole("manager") Then managerOnlyButton.Visible = True End If Catch ex As System.Net.WebException MessageBox.Show("Unable to access the roles service.", _ "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning) End Try End Sub
private void DisplayButtonForManagerRole() { try { if (Thread.CurrentPrincipal.IsInRole("manager")) { managerOnlyButton.Visible = true; } } catch (System.Net.WebException) { MessageBox.Show("Unable to access the role service.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
Если проверка подлинности пройдена успешна, поставщик проверки устанавливает свойство Thread.CurrentPrincipal экземпляру класса ClientRolePrincipal. Этот класс реализует метод IsInRole, который направляет работу настроенному поставщику ролей. Как и ранее, в коде приложения не требуется непосредственной ссылки на поставщика.
Теперь можно запустить приложение и войти в него с учетной записью сотрудника, убедиться в отсутствии кнопки, затем войти с учетной записью руководителя и убедиться в наличии кнопки.
Доступ к веб-параметрам
В следующей процедуре мы добавим в форму текстовое поле и свяжем его с веб-параметром. Как и в более раннем коде, код параметров не будет обращаться непосредственно к поставщику параметров. Вместо этого он использует класс Settings со строгой типизацией (Properties.Settings.Default в C# и My.Settings в Visual Basic), созданный в проекте Visual Studio.
Для использования веб-параметров в пользовательском интерфейсе выполните следующие действия.
Убедитесь, что сервер ASP.NET Web Development Server работает, проверив значок в области уведомлений. Если сервер остановлен, перезапустите приложение (при этом сервер автоматически перезапустится) и закройте окно входа.
В Обозревателе решений выберите проект ClientAppServicesDemo, затем в меню Проект выберите Свойства ClientAppServicesDemo.
Появится конструктор проектов.
На вкладке Параметры щелкните Загрузить веб-параметры.
Появится диалоговое окно Вход.
Введите учетные данные для сотрудника (имя пользователя и пароль "employee") или руководителя (имя пользователя и пароль "manager") и щелкните Вход. Веб-параметр настроен таким образом, что к нему могут получить доступ только те пользователи, которые прошли проверку, поэтому никакие параметры не будут загружены, если щелкнуть Пропустить вход.
Параметр WebSettingsTestText будет отображен в конструкторе со значением DefaultText по умолчанию. Кроме того, для проекта создается класс Settings, содержащий свойство WebSettingsTestText.
В Обозревателе решений в проекте ClientAppServicesDemo выберите форму Form1 и выберите в главном меню Visual Studio Вид | Конструктор.
В конструкторе добавьте в форму элемент управления TextBox.
В окне Свойства укажите свойству (Имя) значение webSettingsTestTextBox.
В редакторе кода для формы добавьте следующий код в конец метода Form1_Load.
Этот код вызывает метод BindWebSettingsTestTextBox, который мы добавим на следующем этапе.
BindWebSettingsTestTextBox()
BindWebSettingsTestTextBox();
Добавьте в конец класса Form1 следующий метод.
Этот метод связывает свойство Text элемента управления webSettingsTestTextBox со свойством WebSettingsTestText класса Settings, созданного ранее. Этот метод также отображает сообщение об ошибке при возникновении WebException, указывающего на недоступность службы веб-параметров.
Private Sub BindWebSettingsTestTextBox() Try Me.webSettingsTestTextBox.DataBindings.Add("Text", _ My.Settings, "WebSettingsTestText") Catch ex As WebException MessageBox.Show("Unable to access the Web settings service.", _ "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning) End Try End Sub
private void BindWebSettingsTestTextBox() { try { this.webSettingsTestTextBox.DataBindings.Add("Text", Properties.Settings.Default, "WebSettingsTestText"); } catch (WebException) { MessageBox.Show("Unable to access the Web settings service.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
Примечание. Обычно привязка данных используется для автоматического двустороннего обмена данными между элементом управления и веб-параметром. Однако можно получить прямой доступ к веб-параметрам, как показано в следующем примере.
webSettingsTestTextBox.Text = My.Settings.WebSettingsTestText
webSettingsTestTextBox.Text = Properties.Settings.Default.WebSettingsTestText;
В конструкторе выберите форму и в окне Свойства нажмите кнопку События.
Выберите событие FormClosing и нажмите клавишу ВВОД для создания обработчика событий.
Замените созданный метод следующим кодом.
Обработчик событий FormClosing вызывает метод SaveSettings, который также используется функцией выхода, которая будет добавлена позже. Метод SaveSettings сначала проверяет, что пользователь не вышел из системы. Для этого он проверяет свойство AuthenticationType элемента IIdentity, возвращенное текущим участником. Текущий участник извлекается из свойства static CurrentPrincipal. Если пользователь прошел проверку подлинности, то тип проверки будет "ClientForms". Метод SaveSettings не может просто проверить свойство IIdentity.IsAuthenticated, поскольку пользователь может иметь действующую учетную запись Windows после выхода.
Если пользователь не выходил их системы, метод SaveSettings вызывает метод Save класса Settings, созданного ранее. Этот метод может создать WebException, если файл "cookie" проверки подлинности истек. Это происходит требуется только в том случае, если в конфигурации приложения был выбран параметр Требовать повторного входа пользователей при истечении "cookie" на сервере. Дополнительные сведения см. в разделе Практическое руководство. Настройка служб клиентских приложений. Метод SaveSettings обрабатывает срок действия файлов "cookie" путем вызова ValidateUser для отображения окна входа. Если пользователь успешно вошел в систему, метод SaveSettings снова пытается сохранить параметры, вызывая самого себя.
Как и ранее, метод SaveSettings отображает сообщение об ошибке, если удаленная служба недоступна. Если поставщик услуг не имеет доступа к удаленной службе, параметры сохраняются в локальном кэше и перезагружаются при перезапуске приложения.
Private Sub Form1_FormClosing(ByVal sender As Object, _ ByVal e As FormClosingEventArgs) Handles Me.FormClosing SaveSettings() End Sub Private Sub SaveSettings() ' Return without saving if the authentication type is not ' "ClientForms". This indicates that the user is logged out. If Not Thread.CurrentPrincipal.Identity.AuthenticationType _ .Equals("ClientForms") Then Return Try My.Settings.Save() Catch ex As WebException If ex.Message.Contains("You must log on to call this method.") Then MessageBox.Show( _ "Your login has expired. Please log in again to save " & _ "your settings.", "Attempting to save settings...") Dim isAuthorized As Boolean = False Try ' Call ValidateUser with empty strings in order to ' display the login dialog box configured as a ' credentials provider. If Not Membership.ValidateUser( _ String.Empty, String.Empty) Then MessageBox.Show("Unable to authenticate. " & _ "Settings were not saved on the remote service.", _ "Not logged in", MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else ' Try again. SaveSettings() End If Catch ex2 As System.Net.WebException MessageBox.Show( _ "Unable to access the authentication service. " & _ "Settings were not saved on the remote service.", _ "Not logged in", MessageBoxButtons.OK, _ MessageBoxIcon.Warning) End Try Else MessageBox.Show("Unable to access the Web settings service. " & _ "Settings were not saved on the remote service.", _ "Not logged in", MessageBoxButtons.OK, _ MessageBoxIcon.Warning) End If End Try End Sub
private void Form1_FormClosing(object sender, FormClosingEventArgs e) { SaveSettings(); } private void SaveSettings() { // Return without saving if the authentication type is not // "ClientForms". This indicates that the user is logged out. if (!Thread.CurrentPrincipal.Identity.AuthenticationType .Equals("ClientForms")) return; try { Properties.Settings.Default.Save(); } catch (WebException ex) { if (ex.Message.Contains("You must log on to call this method.")) { MessageBox.Show( "Your login has expired. Please log in again to save " + "your settings.", "Attempting to save settings..."); try { // Call ValidateUser with empty strings in order to // display the login dialog box configured as a // credentials provider. if (!Membership.ValidateUser(String.Empty, String.Empty)) { MessageBox.Show("Unable to authenticate. " + "Settings were not saved on the remote service.", "Not logged in", MessageBoxButtons.OK, MessageBoxIcon.Error); } else { // Try again. SaveSettings(); } } catch (System.Net.WebException) { MessageBox.Show( "Unable to access the authentication service. " + "Settings were not saved on the remote service.", "Not logged in", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } else { MessageBox.Show("Unable to access the Web settings service. " + "Settings were not saved on the remote service.", "Not logged in", MessageBoxButtons.OK, MessageBoxIcon.Warning); } } }
Добавьте в конец класса Form1 следующий метод.
Этот код обрабатывает событие ClientSettingsProvider.SettingsSaved и отображает предупреждение в том случае, если какие-либо параметры не удается сохранить. Событие SettingsSaved не происходит, если служба параметров недоступна или файл "cookie" проверки подлинности истек. Пример случая, когда событие SettingsSaved произойдет — если пользователь уже вышел из системы. Можно протестировать этот обработчик событий путем добавления кода выхода метод SaveSettings непосредственно перед выходом метода Save. Код выхода описан в следующем разделе.
Private WithEvents settingsProvider As ClientSettingsProvider = My.Settings _ .Providers("System.Web.ClientServices.Providers.ClientSettingsProvider") Private Sub Form1_SettingsSaved(ByVal sender As Object, _ ByVal e As SettingsSavedEventArgs) _ Handles settingsProvider.SettingsSaved ' If any settings were not saved, display a list of them. If e.FailedSettingsList.Count > 0 Then Dim failedSettings As String = String.Join( _ Environment.NewLine, e.FailedSettingsList.ToArray()) Dim message As String = String.Format("{0}{1}{1}{2}", _ "The following setting(s) were not saved:", _ Environment.NewLine, failedSettings) MessageBox.Show(message, "Unable to save settings", _ MessageBoxButtons.OK, MessageBoxIcon.Warning) End If End Sub
private void Form1_SettingsSaved(object sender, SettingsSavedEventArgs e) { // If any settings were not saved, display a list of them. if (e.FailedSettingsList.Count > 0) { String failedSettings = String.Join( Environment.NewLine, e.FailedSettingsList.ToArray()); String message = String.Format("{0}{1}{1}{2}", "The following setting(s) were not saved:", Environment.NewLine, failedSettings); MessageBox.Show(message, "Unable to save settings", MessageBoxButtons.OK, MessageBoxIcon.Warning); } }
Для C# добавьте следующий код в конце метода Form1_Load. Этот код связывает метод, добавленный на предыдущем шаге, с событием SettingsSaved.
((ClientSettingsProvider)Properties.Settings.Default.Providers ["System.Web.ClientServices.Providers.ClientSettingsProvider"]) .SettingsSaved += new EventHandler<SettingsSavedEventArgs>(Form1_SettingsSaved);
Для тестирования приложения на этом этапе запустите его несколько раз, входя в систему с ролью сотрудника и руководителя, и вводите различные значения в текстовое поле. Значения должны сохраняться неизменными для каждого из пользователей.
Реализация выхода из системы
Когда пользователь устанавливает флажок Запомнить меня при входе в систему, приложение будет автоматически выполнять проверку подлинности при следующем запуске. Автоматическая проверка подлинности будет продолжена при работе в автономном режиме и до тех пор, пока не истечет срок действия соответствующего файла "cookie". Однако иногда нескольким пользователям требуется доступ к приложению или одному пользователю может понадобиться войти в приложение, используя разные учетные записи. Для этого в приложении нужно реализовать функцию выхода, описанную ниже.
Чтобы реализовать функциональные возможности выхода из системы, выполните следующие действия.
В конструкторе Form1 добавьте элемент управления Button из панели элементов.
В окне Свойства укажите свойству (Имя) значение logoutButton, а свойству Текст — значение &Выход.
Дважды щелкните logoutButton для создания обработчика события Click.
Откроется редактор кода с курсором на методе logoutButton_Click.
Замените код в методе logoutButton_Click следующим кодом:
Этот обработчик событий сначала вызывает метод SaveSettings, который был добавлен в предыдущем разделе. Затем обработчик событий вызывает метод ClientFormsAuthenticationMembershipProvider.Logout. Если служба проверки подлинности недоступна, метод Logout создает WebException. В этом случае метод logoutButton_Click отображает предупреждающее сообщение и временно переключается в автономный режим для выхода пользователя. Автономный режим описан в следующем разделе.
При выходе из системы локальный файл "cookie" удаляется, поэтому при перезапуске приложения снова нужно выполнить вход. После выхода обработчик событий перезапускает приложение. При перезапуске оно отображает приветствие и окно входа. Отображение приветствие означает, что приложение было перезапущено. Это позволяет избежать путаницы, если пользователь должен войти в систему для сохранения параметров, а затем должен снова войти в систему из-за того, что приложение было перезапущено.
Private Sub logoutButton_Click(ByVal sender As Object, _ ByVal e As EventArgs) Handles logoutButton.Click SaveSettings() Dim authProvider As ClientFormsAuthenticationMembershipProvider = _ CType(System.Web.Security.Membership.Provider, _ ClientFormsAuthenticationMembershipProvider) Try authProvider.Logout() Catch ex As WebException MessageBox.Show("Unable to access the authentication service." & _ Environment.NewLine & "Logging off locally only.", _ "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning) ConnectivityStatus.IsOffline = True authProvider.Logout() ConnectivityStatus.IsOffline = False End Try Application.Restart() End Sub
private void logoutButton_Click(object sender, EventArgs e) { SaveSettings(); ClientFormsAuthenticationMembershipProvider authProvider = (ClientFormsAuthenticationMembershipProvider) System.Web.Security.Membership.Provider; try { authProvider.Logout(); } catch (WebException ex) { MessageBox.Show("Unable to access the authentication service." + Environment.NewLine + "Logging off locally only.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); ConnectivityStatus.IsOffline = true; authProvider.Logout(); ConnectivityStatus.IsOffline = false; } Application.Restart(); }
Для тестирования функциональности выхода запустите приложение и установите флажок Запомнить меня в окне входа. После этого закройте и перезапустите приложение — входить в систему не понадобится. Теперь выйдите из системы, щелкнув "Выход".
Включение автономного режима
В следующей процедуре мы добавим в форму флажок, с помощью которого пользователь сможет включить автономный режим. Приложение обозначает автономный режим, устанавливая свойству static ConnectivityStatus.IsOffline значение true. Значение состояния автономного режима сохраняется на жестком диске локального компьютера в папке, указанной в свойстве Application.UserAppDataPath. Это означает, что значение состояния автономного режима сохраняется для каждого пользователя и для каждого приложения.
В автономном режиме все запросы клиентской службы приложений используют данные, кэшированные в локальной системе, вместо доступа к веб-службам. В конфигурации по умолчанию в локальных данных содержится зашифрованный пароль пользователя. Благодаря этому пользователь может входить в систему и в автономном режиме. Дополнительные сведения см. в разделе Практическое руководство. Настройка служб клиентских приложений.
Включение автономного режима в приложении
В Обозревателе решений в проекте ClientAppServicesDemo выберите форму Form1 и выберите в главном меню Visual Studio Вид | Конструктор.
В конструкторе добавьте в форму элемент управления CheckBox.
В окне Свойства укажите свойству (Имя) значение workOfflineCheckBox, а свойству Текст — значение &Автономный режим.
В окне Свойства нажмите кнопку События.
Выберите событие CheckedChanged и нажмите клавишу ВВОД для создания обработчика события.
Замените созданный метод следующим кодом.
Этот код обновляет значение IsOffline и автоматически выполняет проверку подлинности пользователя при возвращении в оперативный режим. Метод ClientFormsIdentity.RevalidateUser использует кэшированные учетные данные, поэтому пользователю не нужно выполнять вход явным образом. Если служба проверки подлинности недоступна, отображается предупреждение и приложение остается в автономном режиме.
Примечание. Метод RevalidateUser служит исключительно для удобства. У него нет возвращаемого значения, поэтому он не может сообщить о неудаче повторной проверки подлинности. Повторная проверка может оказаться неудачной, например, если на сервере изменились учетные данные пользователя. В этом случае следует добавить в приложение код, который обеспечивал бы явную проверку подлинности пользователей после сбоев вызова службы. Дополнительные сведения см. в разделе "Доступ к веб-параметрам" ранее в этом руководстве.
После повторной проверки подлинности код сохраняет все изменения в веб-параметры локальной системы, вызывая добавленный ранее метод SaveSettings. Затем он получает новые значения на сервере, вызывая метод Reload класса проекта Settings (который вызывается как Properties.Settings.Default в C# и как My.Settings в Visual Basic).
Private Sub workOfflineCheckBox_CheckedChanged( _ ByVal sender As Object, ByVal e As EventArgs) _ Handles workOfflineCheckBox.CheckedChanged ConnectivityStatus.IsOffline = workOfflineCheckBox.Checked If Not ConnectivityStatus.IsOffline Then Try ' Silently re-validate the user. CType(System.Threading.Thread.CurrentPrincipal.Identity, _ ClientFormsIdentity).RevalidateUser() ' If any settings have been changed locally, save the new ' new values to the Web settings service. SaveSettings() ' If any settings have not been changed locally, check ' the Web settings service for updates. My.Settings.Reload() Catch ex As WebException MessageBox.Show( _ "Unable to access the authentication service. " & _ Environment.NewLine + "Staying in offline mode.", _ "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning) workOfflineCheckBox.Checked = True End Try End If End Sub
private void workOfflineCheckBox_CheckedChanged( object sender, EventArgs e) { ConnectivityStatus.IsOffline = workOfflineCheckBox.Checked; if (!ConnectivityStatus.IsOffline) { try { // Silently re-validate the user. ((ClientFormsIdentity) System.Threading.Thread.CurrentPrincipal.Identity) .RevalidateUser(); // If any settings have been changed locally, save the new // new values to the Web settings service. SaveSettings(); // If any settings have not been changed locally, check // the Web settings service for updates. Properties.Settings.Default.Reload(); } catch (WebException) { MessageBox.Show( "Unable to access the authentication service. " + Environment.NewLine + "Staying in offline mode.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); workOfflineCheckBox.Checked = true; } } }
Добавьте следующий код в конец метода Form1_Load, чтобы флажок всегда соответствовал текущему состоянию подключения.
workOfflineCheckBox.Checked = ConnectivityStatus.IsOffline
workOfflineCheckBox.Checked = ConnectivityStatus.IsOffline;
Итак, создание приложения завершено. Для тестирования его в автономном режиме запустите приложение, войдите в него с учетными данными сотрудника или руководителя, и выберите Автономный режим. Измените значение в текстовом поле и закройте приложение. Перезапустите приложение. Перед входом в систему щелкните правой кнопкой значок сервера ASP.NET Development Server в области уведомлений панели задач и выберите Остановить. Затем войдите в систему обычным способом. Несмотря на то что сервер не запущен, можно по-прежнему входить в программу. Измените значение текстового поля, выйдите из программы и перезапустите ее, чтобы задать измененное значение.
Заключение
В этом разделе вы узнали, как включать и использовать службы клиентских приложений в приложении Windows Forms. После настройки тестового сервера вы добавили в приложение код для проверки подлинности пользователей и получения ролей пользователей и параметров приложений с сервера. Также вы узнали, как включать автономный режим, чтобы приложение получало сведения из локального кэша данных, когда подключение к сети недоступно.
Следующие действия
При реальном использовании приложений вам придется получать данные для многих пользователей с удаленного сервера, который может быть не всегда доступен или может отключаться без уведомлений. Для повышения надежности приложения следует обеспечить соответствующую реакцию в случаях, когда служба недоступно. В данном пошаговом руководстве используются блоки "try" и "catch" для перехвата WebException и отображения сообщения об ошибке в случае, когда служба недоступна. В рабочем коде в таких случаях может потребоваться переключаться в автономный режим, завершать работу приложения или отключать доступ к определенным функциям.
Для повышения надежности приложения тщательно протестируйте перед развертыванием и приложение, и сервер.
См. также
Задачи
Практическое руководство. Настройка служб клиентских приложений
Пошаговое руководство. Использование служб приложений ASP.NET
Основные понятия
Общие сведения о службах клиентских приложений
Другие ресурсы
Средство администрирования веб-узла ASP.NET
Создание и настройка базы данных служб приложения для SQL Server
Журнал изменений
Дата |
Журнал событий |
Причина |
---|---|---|
Июль 2008 |
Замененные членство и роль позволяют выполнить пошаговую настройку членства и ролей тестовых классов с использованием средства администрирования веб-узла ASP.NET. |
Улучшение информации. |