С набором разрешений можно работать, используя класс PermissionSet. Методы AddPermission и RemovePermission дают возможность добавлять в набор экземпляры класса, производного от CodeAccessPermission. Тогда методы Deny (Запретить), PermitOnly или Assert (Утвердить) можно применять не к отдельным разрешениям, а к целым их наборам. Таким образом легче указать, что разрешается компонентам и сценариям сторонних производителей. Пример PermissionSet показывает, как это делается.
Вначале мы определяем интерфейс lUserCode, который будет использоваться нашим "проверенным" кодом для доступа к некоторому коду сторонних производителей. Хотя на самом деле этот "сторонний" код обычно располагается в отдельной сборке, но, чтобы не усложнять пример, мы все поместили в одну и ту же сборку.
public _gc _interface lUserCode
// сборщик мусора - интерфейс lUserCode
{
int PotentialRogueCode();
};
public _gc class ThirdParty :
public lUserCode // класс сборщика мусора
ThirdParty: lUserCode
{
public:
int PotentialRogueCode()
{
try {
String *filename = ".\\read.txt"; // Строка
Filelnfo *file = new Filelnfo(filename); // имя файла
StreamReader *sr = file->OpenText(); // файл
String *text; // Строка
text = sr->ReadLine(); // текст
while (text != 0)
// пока (текст != 0)
{
Console::WriteLine(text); // текст text = sr~>ReadLine(); // текст
}
sr->Close(); }
catch(Exception *e) // Исключение
{
Console::WriteLine(e->Message); // Сообщение
}
return 0;
}
};
Наш код создаст новый экземпляр "стороннего" класса, который должен загрузить код в нашу сборку. Затем мы вызываем метод OurCode, передавая ему "сторонний" код.
static int Main()
{
ThirdParty *thirdParty = new ThirdParty;
OurClass *ourClass = new OurClass;
ourClass->OurCode(thirdParty);
return 0;
}
Теперь посмотрим на метод OurCode. Он создает набор разрешений, состоящий из неограниченных разрешений на пользовательский интерфейс и на доступ к файлам. Затем он отменяет разрешения, находящиеся в этом наборе.
void OurCode(lUserCode *code)
{
UlPermission *uiPerm = new UlPermission(
PermissionState::Unrestricted); // Неограниченный
FilelOPermission *fileIOPerm = new FilelOPermission(
PermissionState::Unrestricted); // Неограниченный PermissionSet
*ps =
new PermissionSet(PermissionState::None);
ps->AddPermission(uiPerm) ;
ps->AddPermission(filelOPerm);
ps->Deny();
Console::WriteLine("Permissions denied."); // "Разрешения запрещены."
return;
}
Потом вызывается "сторонний" код. После возврата из него запрет разрешения отменяется и снова вызывается "сторонний" код.
int v = code->PotentialRogueCode();
CodeAccessPermission::RevertDeny();
Console::WriteLine("Permissions allowed.") ;
// "Разрешения позволены."
v = code->PotentialRogueCode() ;
При первом вызове PotentialRogueCode выполнение кода завершается аварийно, а при. втором — успешно. Каждый фрейм в стеке может иметь только один набор разрешений для отказа. Вызывая Deny (Запретить) для набора разрешений, вы перекрываете все остальные вызовы Deny (Запретить) для этого набора в стековом фрейме.