Класс PermissionSet
С набором разрешений можно работать, используя класс 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 (Запретить) для этого набора в стековом фрейме.