Разработка разрешения
Обновлен: Ноябрь 2007
Разрешение предоставляет возможность доступа к защищенному ресурсу или выполнения защищенной операции. При реализации собственно класса разрешения нужно принять несколько высокоуровневых решений по его разработке. Одним из первых шагов является точное определение того, для защиты какого ресурса разрабатывается пользовательское разрешение.
Затем необходимо определить, имеет ли какое-либо значение перекрытие разрешений. Хотя желательно избегать случаев, когда два разрешения защищают один и тот же ресурс, в некоторых ситуациях этого невозможно разумным образом избежать. Например, разрешение на доступ к неуправляемому коду может также заключать в себе другие разрешения, так как код, получающий разрешение на доступ к неуправляемому коду, может выполнять практически любые действия через неуправляемый интерфейс API. Но когда разрешение на доступ к неуправляемому коду не предоставляется, все равно необходимо предоставлять разрешения на доступ к другим определенным ресурсам. Таким образом, имеет смысл отделить разрешение на доступ к неуправляемому коду от других разрешений.
Как определить, что перекрытие областей действия разрешений управляемо? Однозначного ответа на этот вопрос нет, но следует следить за тем, чтобы одно из разрешений предоставляло более раздробленный доступ, чем другое, чтобы в большинстве случаев быть более доступным. В данной ситуации предоставление доступа, как правило, упрощается и облегчает работу администратора.
Определив, какой ресурс будет защищать разрешение и решив все вопросы, касающиеся перекрытия разрешений, следует решить, насколько тонким должно быть управление доступом. Ответ на этот вопрос влияет на способ разработки переменных, предоставляющих состояние разрешения, и определяет, смогут ли администраторы настраивать доступ к защищенному ресурсу. Это также влияет на производительность, легкость использования и другие факторы.
Для иллюстрации некоторых из этих аспектов разработки ниже рассмотрены некоторые принципы, которые могли бы быть избраны при разработке класса FileIOPermission, предоставленного в .NET Framework. Каждое решение влияет на переменные, предоставляющие состояние разрешения.
Одиночный бит, означающий "использовать все файлы" или "не использовать никаких файлов", в зависимости от своего значения.
Два бита, означающие "чтение всех файлов" и "запись всех файлов", или запрет этих действий, в зависимости от их значения.
26 бит, каждый из которых означает "использовать все файлы на указанном диске".
Массив строк, перечисляющий все файлы, к которым предоставляется доступ.
Ясно, что возможны различные варианты для принятия во внимание. Например, однобитное разрешение является очень простым, быстрым и понятным, но оно предоставляет администраторам выбор "все или ничего", что может быть нежелательно. Другие варианты, дающие более сложное представление о состоянии разрешения, могут в некоторой мере снизить производительность. Необходимо взвесить эти варианты и учесть, что не следует создавать более одного разрешения для защиты одного и того же ресурса. Как правило, класс разрешения следует разрабатывать так, чтобы состояние разрешения было настолько сложным, насколько это необходимо, без нанесения значительного урона производительности.
Хотя возможны и другие схемы, большинство разрешений следует одному из следующих стандартных образцов или их сочетания:
Разрешения логического типа. Этот простейший тип разрешения содержит один или более бит, каждый из которых соответствует "разрешению на выполнение действия X". Разрешение либо имеется, либо нет. Примером этого типа разрешения является класс SecurityPermission, чье состояние содержит логические переменные, предоставляющие права на выполнение определенных действий, таких как вызов неуправляемого кода, каждое из которых либо разрешено, либо нет.
Уровни разрешений. Этот более детализированный тип разрешения имеет переменные, предоставляющие каждый вид доступа в виде числа в диапазоне от нуля (означающего полное отсутствие доступа) до некоторого более высокого значения (означающего неограниченный доступ), с несколькими уровнями между этими двумя положениями. Например, можно использовать класс UIPermission для выражения различных уровней доступа к использованию окон, от отсутствия разрешений на пользовательский интерфейс до неограниченных разрешений, с несколькими градациями между ними.
Разрешения в виде списка объектов. Этот тип разрешения предоставляет детальную спецификацию, что разрешено, а что нет. Хорошим примером данного типа разрешения является класс FileIOPermission, так как его состояние представляется списками файлов, для которых разрешены определенные виды доступа. Разрешения со списками наиболее эффективны для защиты ресурсов, содержащих большое количество именованных объектов.
В большинстве случаев желательно минимизировать внешние зависимости в пользовательском классе разрешения, так как каждая сборка, от которой зависит данное разрешение, должна быть загружена, когда системе безопасности потребуется данный класс разрешения. Другая причина минимизации зависимостей состоит в том, что каждая сборка, используемая пользовательским классом разрешения (кроме Mscorlib), должна быть добавлена в список полностью доверенных. Дополнительные сведения см. в разделе Обновление политики безопасности.) Если это возможно, следует помещать пользовательское разрешение и любые классы атрибутов, ассоциированные с ним, в отдельную сборку, чтобы снизить вероятность загрузки других сборок без необходимости.
Примечание. |
---|
Пользовательские разрешения должны быть либо помечены как запечатанные (NotInheritable в Visual Basic), либо иметь присоединенное требование к наследованию. В противном случае вредоносные вызывающие объекты смогут наследовать данное разрешение, что приведет к потенциальным уязвимым местам безопасности. |
См. также
Основные понятия
Создание собственных разрешений доступа к коду