Симон Робинсон - C# для профессионалов. Том II
CodeAccessPermission permission =
new FileIOPermission(FileIOPermissionAccess.Append, @"C:audit.txt");
permission.Deny();
AuditClass.Save("some data to audit");
CodeAccessPermission.RevertDeny();
}
}
class AuditClass {
public static void Save (string value) {
try {
FileIOPermission permission =
new FileIOPermission(FileIOPermissionAccess.Append, @"C:audit.txt");
permission.Assert();
FileStream stream new FileStream(@"C:audit.txt", FileMode.Append, FileAccess.Write);
// код для записи файла контроля здесь
CodeAccessPermission.RevertAssert();
Console.WriteLine("Data written to audit file");
} catch {
Console.WriteLine("Failed to write data to audit file");
}
}
}
}
При выполнении этого кода оказывается, что вызов метода AuditClass не порождает исключения безопасности, несмотря на то, что при вызове он не имел требуемых полномочий для доступа к диску.
Как и в случае RevertDeny(), RevertAssert(), являясь статическим методом, отменяет все заявления в текущей среде выполнения. Важно быть очень осторожным при использовании заявлений. Мы явно присваиваем полномочия методу, вызываемому кодом, который вполне может не иметь этих полномочий. Например, в коде с контролем, даже если политика безопасности диктует, что установленные приложения не могут делать записей на локальный диск, данное приложение выполнит это, если функции контроля были установлены с полномочиями Full Trust.
Создание полномочий доступа к коду
.NET Framework реализует полномочия безопасности доступа к коду, которые предоставляют защиту для ресурсов. Однако в ситуациях, когда необходимо создать свои собственные полномочия, это можно сделать с помощью подклассов CodeAccessPermission. Вывод из этого класса предоставляет возможности системы безопасности доступа к коду из .NET, включая просмотр стека и управление политикой.
Вот два случая, когда может понадобиться создание своих собственных полномочий доступа к коду:
□ Защита ресурса, еще не защищенного с помощью Framework. Например, разработано приложение .NET для автоматизации, которое реализуется с помощью встроенного аппаратного устройства. Создавая свой собственный код полномочий доступа, можно получить достаточно развитый уровень управления доступом для данного устройства автоматизации.
□ Дополнительное ограничение существующих полномочий. Например, хотя .NET Framework дает права, допускающие точный контроль за доступом к локальной файловой системе, можно иметь приложение, где желательно контролировать доступ к определенному файлу или папке более жестко. При таком сценарии полезно создать полномочие доступа к коду, которое связано специально с этим файлом или папкой, и без этого полномочия никакой управляемый код не может получить доступ к этой области на диске.
Декларативная безопасность
Можно отказаться, запросить или заявить полномочия, вызывая классы в .NET Framework, но можно также использовать атрибуты и определять требования полномочий декларативно.
Основное достоинство использования декларативной безопасности состоит в том, что настройки доступны с помощью отражения. Возможность получить доступ к информации посредством отражения дает огромный выигрыш для системных администраторов, которые часто хотят видеть требования безопасности приложений.
Допустим, мы объявляем, что метод для выполнения должен иметь полномочие на чтение с C:.
using System;
using System.Security.Permissions;
namespace SecurityApp8 {
class Class1 {
static void Main(string[] args) {
MyClass.Method();
}
}
[FileIOPermission(SecurityAction.Assert, Read="C:\")]
class MyClass {
public static void Method() {
// реализация находится здесь
}
}
}
Помните, что если атрибуты применяются для заявления или запроса полномочий, невозможно перехватить исключения, возникающие в случае отказа действия, так как не существует обязательного кода, который можно поместить в предложение try-catch-finally.
Чтобы узнать обо всех доступных атрибутах, можно ознакомиться с перечислением System.Security.Permissions.SecurityAction.
Система безопасности на основе ролей
Как мы видели, система безопасности доступа к коду дает CLR возможность неявно решить, должен ли код выполняться и с какими полномочиями на основе свидетельства о коде. В дополнение к этому .NET предоставляет систему безопасности на базе ролей, которая определяет, может ли код выполнить действия на основе свидетельства о пользователе и его роли.
Система безопасности на основе ролей особенно полезна в ситуациях, где доступ к ресурсам является основным вопросом. Хорошим примером может служить отрасль финансов, где роли сотрудников определяют, к какой информации они имеют доступ и какие действия могут выполнить.
Система безопасности на основе ролей также является идеальной для использования в соединении с учетными записями Windows 2000, Microsoft Passport или специальным каталогом пользователя для управления доступом к ресурсам на основе Web. Например, web-сайт может ограничить доступ к своему содержимому, пока пользователь не зарегистрирует свои данные на этом сайте, и затем дополнительно предоставит доступ к специальному содержимому, только если пользователь является оплаченным подписчиком. Во многих отношениях ASP.NET делает систему безопасности на основе ролей проще, так как большая часть кода находится на сервере.
Например, если желательно реализовать службу Web, требующей аутентификации, то можно использовать подсистему учетных записей Windows 2000 и написать метод для Web таким образом, чтобы он проверял, является ли пользователь членом определенной группы пользователей Windows 2000, прежде чем предоставлять доступ к функциональности метода.
Принципал
.NET предоставляет текущему потоку выполнения простой доступ к пользователю приложения, который обозначается как Principal. Принципал является ядром системы безопасности, предоставленной .NET, на основе ролей, и через него можно получить доступ к объекту Identity пользователя, который отображается в учетной записи пользователя одного из приведенных ниже типов:
□ Учетная запись Windows
□ Учетная запись Passport
□ Пользователь, аутентифицированный с помощью cookie из ASP.NET
В качестве дополнительного бонуса система безопасности на основе ролей в .NET может создавать свои собственные принципалы, реализуя интерфейс IPrincipal. Если вы не полагаетесь на аутентификацию Windows, Passport или простую аутентификацию с помощью cookie, необходимо рассмотреть вопрос о создании своей собственной аутентификации с помощью специального класса principal.
С помощью доступа к принципалу можно делать выводы о безопасности на основе идентичности и ролей принципала. Роль является совокупностью пользователей, которые имеют одинаковые полномочия безопасности, и является единицей администрации пользователей. Например, при использовании аутентификации Windows будет применяться тип WindowsIdentity в качестве варианта Identity. Можно выбрать этот тип для выяснения, является ли пользователь членом определенной группы учетных записей пользователей Windows, а затем использовать эту информацию для решения, предоставить или отменить доступ к коду и ресурсам.
Обычно значительно легче управлять безопасностью, если доступ к ресурсам и функциональности разрешается на основе полномочий, а не ролей. Представьте сценарий, где имеется три метода, каждый из них предоставляет доступ к свойству, для которого требуется строгий контроль, чтобы гарантировать, что только авторизованному персоналу доступ к нему открыт. Если приложение имеет, скажем, четырех пользователей, то достаточно легко определить в каждом методе, какие пользователи могут и какие не могут получить доступ к методу. Однако представим ситуацию, где число свойств возрастает до девяти. Чтобы разрешить доступ для дополнительного пользователя, потенциально потребуется изменить каждый из девяти методов, хотя это является административной задачей. Даже хуже, так как пользователи меняются ролями в компании и понадобится изменять код каждый раз, когда это происходит. Если вместо этого реализовать систему, использующую роли, то можно просто добавлять и удалять пользователей из ролей, а не добавлять и удалять отдельных пользователей из приложения. Таким образом, выполнение приложения облегчается, и для каждого метода мы только ставим условие, чтобы пользователь был членом определенной группы. Ото также упрощает управление ролями, так как эту работу может делать администратор, а не разработчик приложения. Говоря проще, разработчик сосредоточивается на том, что, например, Managers, но не Secretaries, могут получить доступ к методу, а не на том, каковы возможности Julie и Bob, но не Conrad.