2009-03-02 4 views
4

В этом коде я хотел бы, чтобы метод ReadFileSystem был запрещен для подтверждения разрешения на файловую систему.Как отрицать Assert с CAS?

Я ожидал, что это будет выбрано fileIo.Assert(), но это не так. Зачем?

using System.Security.Permissions; 
static void Main(string[] args) 
{ 
    var fileIo = new FileIOPermission(PermissionState.Unrestricted); 
    var secuPerm = new SecurityPermission(SecurityPermissionFlag.Assertion); 
    PermissionSet set = new PermissionSet(PermissionState.Unrestricted); 
    set.AddPermission(fileIo); 
    set.AddPermission(secuPerm); 
    set.Deny(); 
    ReadFileSystem(); 
    Console.Read(); 
} 

private static void ReadFileSystem() 
{ 
    var fileIo = newFileIOPermission(PermissionState.Unrestricted); 
    fileIo.Assert(); 

    DirectoryInfo dir = new DirectoryInfo("C:/"); 
    dir.GetDirectories(); 
} 

Update

Великая ссылка здесь на CAS: http://blogs.msdn.com/shawnfa/archive/2004/08/25/220458.aspx

ответ

8

Последующее Assert отрицает эффекты Deny.

Способность утверждать FileIOPermission в основном зависит от того, доверяет ли ваша сборка. На него не влияет предыдущий отказ от FileIOPermission. Оказывается, на него также не повлиял предыдущий отказ в утверждении SecurityPermission. Это потому, что SecurityPermissionFlag.Assertion проверяется как требование времени соединения. Это явно не задокументировано; Я нашел его here.

Чтобы заставить CLR не доверять вашей сборке для FileIOPermission, вы можете использовать следующее в верхней части файла после операторов using. Когда вы добавите это в свой файл, утверждение не вступит в силу. Это влияет на всю сборку. Нет более тонкой детализации.

[assembly:FileIOPermission(SecurityAction.RequestRefuse, Unrestricted=true)] 
+0

binarycoder точно прав. .NET редко утверждает внутренне ... Обычно это требует. Спрос - это то, что делает стек, который найдет отрицание в стеке и потерпит неудачу. Для всех файлов IO .NET выполняет запрос. Но как только он найдет Assert в стеке, стековая прогулка прекращается. –

+0

И как предложил binarycoder, единственный способ заставить Assert выполнять свою работу - это лишить всю сборку разрешений, которые вы пытаетесь утвердить, эффективно делая свою сборку с частичным доверием. Частичное доверие - это хорошо, но если вы не хотите иметь возможность называть Assert, просто не называйте его? –

+0

@ Андрей, я хотел быть уверенным, что любой вызов после моего Assert не может получить доступ к жесткому диску. Поскольку мой вариант использования заключался в том, чтобы вызвать другую сборку через отражение (не доверенный), без необходимости настраивать данные при загрузке. Наконец, это то, что я сделал. Но это поведение CAS заинтриговало меня. –

1

Хороший вопрос наверняка. Я запустил код и немного озадачен. Я просто провожу час или 2, изучая документы и поиск в Интернете, но безрезультатно. Обратите внимание, что MSDN завершает работу, выполняя запрос «Спрос на утверждение».

Редактировать: ответ binarycoder указал мне в правильном направлении.

Права на защиту просто недействительны в сборке с полным ходом. Только если вы добавите следующее в верхнюю часть файла:

[assembly: SecurityPermissionAttribute(SecurityAction.RequestRefuse, Assertion = true)] 

вызов файлаIo.Assert() не удастся.

Но в противном случае попытка Запретить() разрешение утверждения и следующий атрибут полностью неэффективны (если только вы явно не задаете() права утверждения).

[SecurityPermissionAttribute(SecurityAction.Deny, Assertion = true)] 
private static void ReadFileSystem() {} 

Документация заявляет что Assert() «имеет некоторые проблемы безопасности» и рекомендация всегда Требуйте-Before-Утверждай:

fileIo.Demand(); 
fileIo.Assert(); 

, но я до сих пор перенастраивать свой образ мышления о применении принципа наименьших привилегий.

+0

Зачем нам требовать и утверждать после? Можете ли вы дать мне свой источник? Потому что, если Demand Ok, я не понимаю, почему мы должны делать утверждение после. Я помнил, что читал что-то об этом шаблоне, это было преобразование разрешений (например, IOPermission + SecurityPermission => CustomPermission). –

+0

Единственный источник, который у меня есть, - это powerpoint: http://www.bristowe.com/presentations/Code%20Access%20Security.ppt В принципе, Demand - это ваш чек, а Assert - ускорение для нижестоящего кода. –

2

Я думаю, вы можете неправильно понять цель утверждения разрешений. Когда вы утверждаете набор разрешений в CAS, вы фактически говорите: «Я знаю, что я делаю ... Мне все равно, какие разрешения глубже в стеке». Это почти никогда что вы хотите. Обычно вы хотите потребовать набор разрешений. Это вызывает прохождение стека, в результате которого в стеке обнаружен Deny, а затем возникнет исключение безопасности.

Однако, поскольку.NET имеет практически все необходимые Demands встроенные, редко требуется на самом деле требовать что-либо, если вы не выполняете Asserts (опять же, это редко), или вы написали свой собственный класс Permission.

+0

Да, я знаю это, но я подумал, что когда мы делаем Assert, для SecurityPermission есть стек. (MSDN четко говорит, что вы можете утверждать, имеет ли ваша сборка разрешение на утверждённое разрешение и что у вас есть SecurityPermission, предоставленная на вашей сборке). –

+0

Ни одна из тех вещей, о которых говорит MSDN, требует перехода в стек. –

+0

Конечно, это была моя ошибка. Но ваша сборка должна быть разрешена с помощью знака SecurityPermission и Assertion. (В конфигурации .NET или внутри вашего кода сборки, например, двоичный код) –

 Смежные вопросы

  • Нет связанных вопросов^_^