|
При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан. Затем: Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз. |
Безопасность Windows-форм
Объект "личность"
Объекты "личность" и "роль" применяются для доступа к информации о пользователе. Мы можем использовать информацию об имени встроенной учетной записи в операционной системе Windows и роли этой учетной записи с помощью объектов WindowsIdentity и WindowsPrincipal. Для доступа к информации о пользователе, основанной на собственном механизме аутентификации, задействуются объекты GenericIdentity и GenericPrincipal.
Объект "личность" инкапсулирует такую информацию о пользователе, как имя и тип аутентификации. В библиотеке .NET Framework есть три типа объекта "личность" (таблица 10.6).
| Личность | Описание |
|---|---|
| Windows Identity | Представляет информацию о текущей учетной записи Windows. Windows Identity позволяет определять полномочия пользователя в ОС и использовать их в приложении. Реализуется классом WindowsIdentity |
| Generic Identity | Представляет информацию о пользователе, которая основана на частном механизме аутентификации, используемом в приложении. Реализуется классом GenericIdentity |
| Custom Identity | Представляет "личность", которая инкапсулирует частную информацию о пользователе. Реализуется классом, в котором имеется интерфейс IIdentity |
Все классы, описывающие "личность", должны реализовывать интерфейс IIdentity. Интерфейс IIdentity имеет три открытых свойства:
- Name — имя пользователя.
- IsAuthenticated — логическая переменная, принимающая одно из двух значений в зависимости от результата прохождения пользователем аутентификации.
- AuthenticationType — тип аутентификации пользователя.
Объект "роль"
"Роль" определяет право пользователей на выполнение действий, причем возможно наличие нескольких пользователей (входящих в группу) с различными именами, но равными ролями. Практически такая ситуация характерна для информационных систем — например, в банке права менеджера и оператора различаются, причем может быть несколько как менеджеров, так и операторов.
В библиотеке .NET Framework есть три типа объекта "роль" (таблица 10.7).
Все классы, описывающие объект "роль", должны реализовывать интерфейс 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 (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 (Code\Glava10\ GenericIdentityandPrincipal).


