Опубликован: 11.09.2006 | Доступ: свободный | Студентов: 7649 / 473 | Оценка: 4.26 / 3.45 | Длительность: 30:46:00
ISBN: 978-5-9556-0080-2
Лекция 10:

Безопасность Windows-форм

Объект "личность"

Объекты "личность" и "роль" применяются для доступа к информации о пользователе. Мы можем использовать информацию об имени встроенной учетной записи в операционной системе Windows и роли этой учетной записи с помощью объектов WindowsIdentity и WindowsPrincipal. Для доступа к информации о пользователе, основанной на собственном механизме аутентификации, задействуются объекты GenericIdentity и GenericPrincipal.

Объект "личность" инкапсулирует такую информацию о пользователе, как имя и тип аутентификации. В библиотеке .NET Framework есть три типа объекта "личность" (таблица 10.6).

Таблица 10.6. Типы объекта личность .NET Framework
Личность Описание
Windows Identity Представляет информацию о текущей учетной записи Windows. Windows Identity позволяет определять полномочия пользователя в ОС и использовать их в приложении. Реализуется классом WindowsIdentity
Generic Identity Представляет информацию о пользователе, которая основана на частном механизме аутентификации, используемом в приложении. Реализуется классом GenericIdentity
Custom Identity Представляет "личность", которая инкапсулирует частную информацию о пользователе. Реализуется классом, в котором имеется интерфейс IIdentity

Все классы, описывающие "личность", должны реализовывать интерфейс IIdentity. Интерфейс IIdentity имеет три открытых свойства:

  • Name — имя пользователя.
  • IsAuthenticated — логическая переменная, принимающая одно из двух значений в зависимости от результата прохождения пользователем аутентификации.
  • AuthenticationType — тип аутентификации пользователя.

Объект "роль"

"Роль" определяет право пользователей на выполнение действий, причем возможно наличие нескольких пользователей (входящих в группу) с различными именами, но равными ролями. Практически такая ситуация характерна для информационных систем — например, в банке права менеджера и оператора различаются, причем может быть несколько как менеджеров, так и операторов.

В библиотеке .NET Framework есть три типа объекта "роль" (таблица 10.7).

Таблица 10.7. Типы объекта роль .NET Framework
Роль Описание
Windows Principal Представляет пользователей операционной системы Windows и их роли. Реализуется классом WindowsPrincipal
Generic Principal Представляет независимых от операционной системы пользователей и их роли. Реализуется классом GenericPrincipal
Custom Principal Представляет специальную для приложения информацию о ролях. Реализуется классом, в котором имеется интерфейс IPrincipal

Все классы, описывающие объект "роль", должны реализовывать интерфейс IPrincipal. Интерфейс IPrincipal имеет одно свойство — Identity, которое описывает объект класса, реализующего интерфейс Iidentity, и метод — IsInRole, который определяет, принадлежит ли текущий "принципал" к заданной роли.

Использование объектов WindowsIdentity и WindowsPrincipal

Существует два способа создания объекта WindowsPrincipal. Разница между ними в том, что один способ проверяет введенную информацию один раз, а второй — постоянно.

Если однократной проверки роли достаточно, то создаем объект WindowsPrincipal следующим образом:

// Инициализируем объект класса WindowsIdentity
    // с помощью статического метода WindowsIdentity.GetCurrent()
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    // Создаем новый объект класса WindowsPrincipal
   // и передаем в качестве параметра объект identity
WindowsPrincipal principal = new WindowsPrincipal(identity);

Если же вам необходимо проверять роль пользователя постоянно, то лучше создать объект WindowsPrincipal следующим образом:

// Указываем домену приложения политику ролевой безопасности
   // с помощью члена WindowsPrincipal перечисления PrincipalPolicy,
   // переданного в статический метод AppDomain.CurrentDomain.
// SetPrincipalPolicy.
AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
   // После того как новая политика установлена, вы можете использовать
   // объект из статического свойства CurrentPrincipal класса Thread.
WindowsPrincipal principal = System.Threading.Thread.CurrentPrincipal
as WindowsPrincipal;

Создайте новое консольное приложение и назовите его WindowsIdentityandPrincipal. Далее привожу листинг с комментариями:

using System;
//Подключаем пространства имен Threading и Principal
using System.Threading;
using System.Security.Principal;

namespace WindowsIdentityandPrincipal
{

        class Class1
        {
                [STAThread]
                static void Main(string[] args)
                {
                        // Создаем и инициализируем объекты
                        // WindowsPrincipal и WindowsIdentity
                        WindowsIdentity identity = WindowsIdentity.GetCurrent();
                        WindowsPrincipal principal = new WindowsPrincipal(identity);
                        // Выводим информацию, содержащуюся в объекте класса WindowsPrincipal
                        Output("Name", principal.Identity.Name);
                        Output("Type", principal.Identity.AuthenticationType);
                        Output("Authenticated", principal.Identity.IsAuthenticated.ToString());
                        // Выводим информацию, содержащуюся в объекте класса WindowsIdentity
                        Output("IdentName", identity.Name);
                        Output("IdentType", identity.AuthenticationType);
                        Output("IdentIsAuthenticated", identity.IsAuthenticated.ToString());
                        Output("IsAnonymous",  identity.IsAnonymous.ToString());
                        Output("IsGuest",  identity.IsGuest.ToString());
                        Output("IsSystem", identity.IsSystem.ToString());
                        Output("Token", identity.Token.ToString());
                }

                //Метод Output выводит информацию на экран, причем myName — это название
                //параметра, а myValue — его значение.
                public static void Output(string myName, string myValue)
                {
                        Console.WriteLine(myName + "= {0}", myValue);
                }
Листинг 10.2.

В результате выводится полный список значений WindowsIdentity и WindowsPrincipal на данном компьютере (рис. 10.12).

Результат приложения WindowsIdentityandPrincipal

Рис. 10.12. Результат приложения WindowsIdentityandPrincipal

На диске, прилагаемом к книге, вы найдете приложение WindowsIdentityandPrincipal (Code\Glava10\ WindowsIdentityandPrincipal).

Использование объектов GenericIdentity и GenericPrincipal

Классы GenericPrincipal совместно с классом GenericIdentity применяются для реализации ролевой безопасности, не зависящей от системы безопасности Windows. Например, у пользователя запрашиваются имя и пароль, которые затем сверяются с данными, хранящимися в приложении или локальной базе данных, и, после успешной проверки, создаются объекты GenericPrincipal и GenericIdentity на основании введенных значений.

Для реализации ролевой безопасности на основе объектов классов GenericPrincipal и GenericIdentity необходимо выполнить следующие действия:

  • создать новый объект класса GenericIdentity и инициализировать его именем пользователя;
  • создать новый объект класса GenericPrincipal и инициализировать его только что созданным объектом класса GenericIdentity и строковым массивом, содержащим роли пользователя;
  • прикрепить созданный объект класса GenericPrincipal к текущему потоку. Прикрепление к текущему потоку необходимо для осуществления последующей проверки полномочий пользователя в коде приложения.

Синтаксис этих действий следующий:

// Создаем и инициализируем именем пользователя
// объект класса GenericIdentity
GenericIdentity identity = new GenericIdentity("Username");
// Создаем строковый массив, содержащий роли пользователя.
string[] userRoles = new string[]{"Administrator", "PowerUser", "GuestUser"};
// Создаем объект класса GenericPrincipal и инициализируем его
// объектом класса GenericIdentity identity и строковым массивом с
// ролями.
GenericPrincipal principal = new GenericPrincipal(identity, userRoles);
// Прикрепляем объект роли к текущему процессу.
// Этот и все дочерние процессы будут иметь данную роль.
Thread.CurrentPrincipal = principal;

Создайте новое консольное приложение и назовите его GenericIdentityandPrincipal . Далее привожу листинг с комментариями:

using System;
using System.Threading;
using System.Security.Principal;

namespace GenericIdentityandPrincipal
{
        /// <summary>
        /// Summary description for Class1.
        /// </summary>
        class Class1
        {
                [STAThread]
                static void Main(string[] args)
                {
                        // Создаем и прикрепляем объект роли.
                        CreateGenericPrincipalAndIdentity(Roles.PowerUser);
                        // Вводим один из способов осуществления проверки роли.
                        if(Thread.CurrentPrincipal.IsInRole("User"))
                        {
                                Console.WriteLine("У вас нет прав для работы с этим приложением");
                        }
                        else if(Thread.CurrentPrincipal.IsInRole("PowerUser"))
                        {
                                Console.WriteLine("Добро пожаловать, {0}. Ваша роль — Продвинутый пользователь", Thread.CurrentPrincipal.Identity.Name);
                        }
                        else // Administrator
                        {
                                Console.WriteLine("Добро пожаловать, {0}. Ваша роль — Администратор", Thread.CurrentPrincipal.Identity.Name);
                        }
                }

                // Создание объектов личности и роли

                static void CreateGenericPrincipalAndIdentity(Roles role)
                {
                        // Создаем и инициализируем именем пользователя
                        // объект класса GenericIdentity
                        GenericIdentity identity = new GenericIdentity("Username");
                        // Создаем строковый массив, содержащий роли пользователя.
                        string[] userRoles = new string[]{role.ToString()};
                        //  Создаем объект класса GenericPrincipal и инициализируем его
                        // объектом класса GenericIdentity identity и строковым массивом с ролями.
                        GenericPrincipal principal = new GenericPrincipal(identity, userRoles);
                        // Прикрепляем объект роли к текущему процессу.
                        // Этот и все дочерние процессы будут иметь данную роль.
                        Thread.CurrentPrincipal = principal;
                }
                enum Roles
                {
                        Administrator,
                        PowerUser,
                        User
                }
        }
}
Листинг 10.3.

Если пользователь проходит проверку, он получает дальнейший доступ (рис. 10.13).

Результат приложения GenericIdentityandPrincipal

Рис. 10.13. Результат приложения GenericIdentityandPrincipal

На диске, прилагаемом к книге, вы найдете приложение GenericIdentityandPrincipal (Code\Glava10\ GenericIdentityandPrincipal).

Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/