Как получить доступ к критическому полю безопасности от анонимного делегата или лямбда?
Сценарий
Скажем, у нас есть следующий код:
[SecuritySafeCritical]
public void SomeMethod()
{
SomeCriticalClass critical = new SomeCriticalClass();
Action someDelegate = () =>
{
critical.Do();
}
someDelegate();
}
- Подписи
SomeMethod
имеет атрибут [SecuritySafeCritical]
.
-
SomeCriticalClass
- это некоторый класс, который имеет атрибут [SecurityCritical]
либо на уровне метода, либо на методе Do
.
- Мы создаем анонимный делегат, автоматически определяемый
Action
.
Проблема
Вызов critical.Do()
вызывает MethodAccessException
FieldAccessException
, потому что прозрачный метод безопасности (анонимный метод) пытается получить доступ к критическому значению безопасности (локальная переменная critical
SomeCriticalClass).
Вопрос
Как вы преодолеваете это?
Простым способом будет использование фактического метода, помеченного [SecuritySafeCritical]
вместо использования анонимного делегата. Но это приводит нас к анонимным делегатам и эры lambas. Я не хочу этого.
Другим простым способом было бы просто не использовать прозрачность безопасности. Это не решение.
Почти все доступные библиотеки как из Microsoft, так и из сообщества с открытым исходным кодом не разработаны с учетом прозрачности безопасности. То есть любой собственный код должен взаимодействовать с сторонними библиотеками через [SecuritySafeCritical]
или [SecurityCritical]
методы/свойства/делегаты.
На самом деле я считаю, что прозрачность безопасности - хороший инструмент, потому что он создает лучшие и безопасные разработки программного обеспечения, критические действия очень локализованы, а остальная часть кода работает с минимальными разрешениями.
Ответы
Ответ 1
Извините, но я не мог дождаться других ответчиков... Я получил решение!
В результате экспериментов я мог определить, что маркировка с [SecuritySafeCritical]
классом, у которого есть метод, который создает анонимный метод в своем теле, делает трюк!!
Другими словами, или говоря о коде:
[SecurityCritical]
public class SomeCriticalClass
{
[SecurityCritical]
public void Do()
{
}
}
[SecuritySafeCritical]
public sealed class SomeClass
{
[SecuritySafeCritical]
public void SomeMethod()
{
SomeCriticalClass critical = new SomeCriticalClass()
// No more FieldAccessException!
Action action = () => critical.Do();
}
}
Я хочу сделать некоторые пояснения:
-
Маркировка класса SomeClass
с помощью [SecuritySafeCritical]
не означает, что все объявленные методы будут [SecuritySafeCritical]
по умолчанию. Это означает, что класс может использоваться частично доверенными абонентами. Вы по-прежнему должны отмечать атрибутом [SecuritySafeCritical]
те методы, свойства или поля, к которым могут обращаться частично доверенные абоненты.
-
Похоже, что [SecuritySafeCritical]
на уровне класса создает локальные переменные и анонимные методы (возможно, анонимные объекты тоже!) безопасно безопасно.
Да! Я надеюсь, что и мой вопрос, и мой собственный ответ будут полезны для всех, потому что я считаю, что ситуация, описанная в моем вопросе, может часто случаться!