Что ж, мне наконец-то удалось взорвать программу как прямую причину неудавшегося требования наследования.
Вам понадобится решение VS с тремя проектами.
Первый базовый класс:
using System;
using System.IO;
using System.Security;
using System.Security.Permissions;
namespace BaseClass
{
public abstract class IniPrinterBase
{
[FileIOPermission(SecurityAction.Deny, AllFiles = FileIOPermissionAccess.Read)]
//[RegistryPermission(SecurityAction.InheritanceDemand,Unrestricted = true)]
public virtual void PrintIniFile()
{
ProtectedPrint();
}
protected void ProtectedPrint()
{
try
{
var lines = File.ReadAllLines(@"G:\test.ini");
foreach (var line in lines)
{
Console.WriteLine(line);
}
}
catch (SecurityException e)
{
Console.WriteLine("PRINT OF INI FILE FAILED!");
Console.WriteLine(e.Message);
}
}
}
}
Затем производные классы в другом проекте:
using System.Security.Permissions;
using BaseClass;
[assembly:RegistryPermission(SecurityAction.RequestRefuse,Unrestricted = true)]
namespace DerivedClasses
{
public class FileIOPermissionExceptionThrower : IniPrinterBase
{
public override void PrintIniFile()
{
base.PrintIniFile();
}
}
public class InheritanceDemandExceptionThrower : IniPrinterBase
{
public override void PrintIniFile()
{
ProtectedPrint();
}
}
}
и, наконец, основная программа в третьем проекте:
using System;
using DerivedClasses;
namespace MethodSecuritySpike
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Printing ini file from security enforced method:");
var printer1 = new FileIOPermissionExceptionThrower();
printer1.PrintIniFile();
Console.WriteLine();
Console.WriteLine("Bypassing security:");
var printer2 = new InheritanceDemandExceptionThrower();
printer2.PrintIniFile();
Console.ReadLine();
}
}
}
Чтобы пример работал, вы должны обратиться к сборке BaseClass в сборке DerivedClasses и к сборкам BaseClass и DerivedClasses в сборке MethodSecuritySpike.
Кроме того, создайте соответствующий файл test.ini в любом другом месте, кроме корня C: \ (в противном случае защита Windows может подшутить над вами)
Запустите программу (MethodSecuritySpike.exe). Сначала вы увидите, что при попытке прочитать INI-файл перехватывается исключение, после чего содержимое INI-файла, тем не менее, отображается.
Затем удалите косые черты комментария перед атрибутом RegistryPermissionAttribute в пространстве имен BaseClass. Запустите программу: она вообще не запускается!
Объяснение атрибутов:
В Baseclass:
[FileIOPermission (SecurityAction.Deny, AllFiles = FileIOPermissionAccess.Read)] * 1018 *
Вызовет исключение, когда PrintIniFile вызывается в базовом классе (имитирует ситуацию, в которой Code Access Security пытается предотвратить доступ к INI-файлу)
Класс InheritanceDemandExceptionThrower обходит это объявление безопасности, переопределяя метод PrintIniFile и напрямую вызывая метод ProtectedPrint. (Имитация нарушения безопасности)
[RegistryPermission (SecurityAction.InheritanceDemand, Unrestricted = true)]
Требует, чтобы классы, наследуемые от IniPrinterBase, имели указанное выше разрешение (произвольно выбранное, поскольку для него потребуется высокий уровень доверия)
Поскольку DerivedClasses.dll явно отказано в этом разрешении, программа не запускается, если этот атрибут не закомментирован.
В производных классах:
[сборка: RegistryPermission (SecurityAction.RequestRefuse, Unrestricted = true)]
Указывает, что запрос на RegistryAccess должен быть отклонен (имитирует среду с частичным доверием). Обычно это не вызывает исключения, так как классы в DerivedClasses.dll не обращаются к реестру.
Однако, когда требование наследования активизировано, DerivedClasses.dll требуется разрешение реестра, чтобы иметь возможность создания экземпляров его двух классов и разрывается.
Легко! ; -)