Безопасность частичного доверия в WPF

В общем случае, чтобы избежать злонамеренного повреждения, веб-приложения не должны иметь прямой доступ к критическим системным ресурсам. По умолчанию HTML и клиентские языки скриптов не имеют доступа к критическим системным ресурсам. Поскольку приложения Windows Presentation Foundation (WPF), реализованные в обозревателе, можно запускать из обозревателя, то они должны соответствовать аналогичному набору ограничений. Для принудительного применения этих ограничений WPF использует и Code Access Security (CAS), и ClickOnce (см. раздел Стратегия безопасности WPF — безопасность платформы). По умолчанию приложения, реализованные в браузере, запрашивают набор разрешений зоны Интернета CAS, независимо от того, запускаются ли они из Интернета, из локальной интрасети или с локального компьютера. Приложения, имеющие не полный набор разрешений, выполняются "с частичным доверием".

WPF предоставляет широкую поддержку того, чтобы при частичном доверии можно было безопасно использовать максимально возможную функциональность, и, как и CAS, обеспечивает поддержку программирования с использованием частичного доверия.

В этом разделе содержатся следующие подразделы.

  • Поддержка частичного доверия функциями WPF

  • Программирование с использованием частичного доверия

  • Управление разрешениями

Поддержка частичного доверия функциями WPF

В следующей таблице перечислены функции высокого уровня Windows Presentation Foundation (WPF), являющиеся безопасными для использования в пределах набора разрешений зоны Интернета.

Таблица 1. Безопасные в частичном доверии функции WPF

Область функций

Функция

Общие

Окно обозревателя

Доступ к узлу источника

IsolatedStorage (ограничение 512KB)

Поставщики UIAutomation

Управление

Редакторы методов ввода (IME)

Перо планшета и рукописный ввод

Моделирование перетаскивания с помощью событий захвата и перемещения мыши

OpenFileDialog

Десериализация языка XAML (с помощью XamlReader.Load)

Веб-интеграция

Диалоговое окно загрузки обозревателя

Верхний уровень инициированной пользователем навигации

ссылки "mailto:"

Параметры универсального кода ресурса (URI)

HTTPWebRequest

Содержимое WPF, размещенное в IFRAME

Размещение HTML-страниц одного веб-узла с помощью элемента управления Frame

Размещение HTML-страниц одного веб-узла с помощью элемента управления WebBrowser

Веб-службы (ASMX)

Веб-службы (использующие Windows Communication Foundation)

Сценарии

Модель DOM

Визуальные

2D и 3D

Анимация

Мультимедиа (от узла источника и междоменное)

Обработка изображений/аудио/видео

Чтение

FlowDocuments

Документы XPS

Внедренные и системные шрифты

Шрифты CFF и TrueType

Редактирование

Проверка орфографии

RichTextBox

Поддержка помещения в буфер обмена незашифрованного текста и рукописного ввода

Команда "Вставить" инициированная пользователем

Копирование выбранного содержимого

Элементы управления

Общие элементы управления

В этой таблице приводятся функции WPF высокого уровня. Дополнительные сведения, о разрешениях, необходимых каждому элементу WPF см. в документах Windows Software Development Kit (SDK). Кроме того, для следующих функций имеются дополнительные сведения, касающиеся выполнения при частичном доверии, включающие некоторые особенности.

В следующей таблице описываются функции WPF, которые не являются безопасными для выполнения в пределах набора разрешений зоны Интернета.

Таблица 2. Не безопасные в частичном доверии функции WPF

Область функций

Функция

Общие

Окна (определенные приложением окна и диалоговые окна)

SaveFileDialog

Файловая система

Доступ к реестру

Перетаскивание

Сериализация языка XAML (с помощью XamlWriter.Save)

Клиенты UIAutomation

Доступ к окну источника (HwndHost)

Полная поддержка управления речью

Взаимодействие с Windows Forms

Визуальные

Эффекты для точечных рисунков

Кодировка изображения

Редактирование

Копирование в буфер обмена формата RTF

Полная поддержка языка XAML

Программирование с использованием частичного доверия

Для приложений XBAP код, превышающий набор разрешений по умолчанию, имеет другое поведение (в зависимости от зоны безопасности). В некоторых случаях пользователю выдается предупреждение при попытке установки. Пользователь может выбрать, продолжить или отменить установку. В следующей таблице описывается поведение приложения в каждой зоне безопасности и указываются действия, необходимые, чтобы приложение получило полное доверие.

Зона безопасности

Поведение

Получение полного доверия

Локальный компьютер

Автоматическое получение полного доверия

Никаких действий не требуется.

Интрасеть и надежные сайты

Вывод диалогового окна с запросом о полном доверии

Заверьте модуль XBAP сертификатом, чтобы его источник отображался в диалоговом окне запроса.

Интернет

Сбой с сообщением "Доверие не предоставлено"

Заверьте модуль XBAP сертификатом.

ПримечаниеПримечание

Поведение, приведенное в предыдущей таблице, относится к XBAP, не следующим модели доверенного развертывания ClickOnce.

В общем случае код, который может выходить за рамки доступных разрешений, вероятно, является общим кодом, который доступен как отдельным приложениям, так и приложениям, работающим в браузере. CAS и WPF предлагают несколько технологий для таких случаев.

Определение разрешений с помощью управления доступом для кода (CAS)

В некоторых случаях общий код в сборках библиотек может использоваться как отдельными приложениями, так и XBAPs. В этих случаях код может выполнять функции, которые могут потребовать больше разрешений, чем позволяет набор разрешений, присвоенный приложению. Приложение может определять, имеет ли оно определенные разрешения, используя безопасность Microsoft .NET Framework. В частности, приложение может проверить, обладает ли оно определенным разрешением, вызвав метод Demand для экземпляра нужного разрешения. Это показано в следующем примере, имеющим код, который уточняет, имеет ли он имеет возможность сохранить файл на локальный диск:


Imports System.IO ' File, FileStream, StreamWriter
Imports System.IO.IsolatedStorage ' IsolatedStorageFile
Imports System.Security ' CodeAccesPermission, IsolatedStorageFileStream
Imports System.Security.Permissions ' FileIOPermission, FileIOPermissionAccess
Imports System.Windows ' MessageBox

Namespace SDKSample
    Public Class FileHandling
        Public Sub Save()
            If IsPermissionGranted(New FileIOPermission(FileIOPermissionAccess.Write, "c:\newfile.txt")) Then
                ' Write to local disk
                Using stream As FileStream = File.Create("c:\newfile.txt")
                Using writer As New StreamWriter(stream)
                    writer.WriteLine("I can write to local disk.")
                End Using
                End Using
            Else
                MessageBox.Show("I can't write to local disk.")
            End If
        End Sub

        ' Detect whether or not this application has the requested permission
        Private Function IsPermissionGranted(ByVal requestedPermission As CodeAccessPermission) As Boolean
            Try
                ' Try and get this permission
                requestedPermission.Demand()
                Return True
            Catch
                Return False
            End Try
        End Function



...


    End Class
End Namespace
using System.IO; // File, FileStream, StreamWriter
using System.IO.IsolatedStorage; // IsolatedStorageFile
using System.Security; // CodeAccesPermission, IsolatedStorageFileStream
using System.Security.Permissions; // FileIOPermission, FileIOPermissionAccess
using System.Windows; // MessageBox

namespace SDKSample
{
    public class FileHandling
    {
        public void Save()
        {
            if (IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c:\newfile.txt")))
            {
                // Write to local disk
                using (FileStream stream = File.Create(@"c:\newfile.txt"))
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    writer.WriteLine("I can write to local disk.");
                }
            }
            else
            {
                MessageBox.Show("I can't write to local disk.");
            }
        }

        // Detect whether or not this application has the requested permission
        bool IsPermissionGranted(CodeAccessPermission requestedPermission)
        {
            try
            {
                // Try and get this permission
                requestedPermission.Demand();
                return true;
            }
            catch
            {
                return false;
            }
        }



...


    }
}

Если приложение не имеет нужных разрешений, вызов Demand вызывает исключение безопасности. В противном случае, разрешение было предоставлено. IsPermissionGranted инкапсулирует это поведение и возвращает значения true или false соответственно.

Постепенное снижение функциональности

Возможность обнаружения, имеет ли код разрешения для выполнения необходимых ему действий является выгодной для кода, который может выполняться из различных зон. Определение зоны — это полезная возможность, однако гораздо лучше предоставить выбор пользователю, если возможно. Например, приложение полного доверия обычно позволяет пользователям создавать файлы в любом желаемом месте, в то время как приложение частичного доверия может создавать файлы только в изолированном хранилище. Если код создания файла существует в сборке, которая совместно используется и приложениями с полным доверием (отдельные приложения), и приложениями с частичным доверием (приложения, реализованные в браузере), и нужно, чтобы оба приложения давали пользователям возможность создавать файлы, то до создания файла в соответствующем приложении общий код должен определить, выполняется ли он при частичном или полном доверии. Это демонстрируется в следующем коде.


Imports System.IO ' File, FileStream, StreamWriter
Imports System.IO.IsolatedStorage ' IsolatedStorageFile
Imports System.Security ' CodeAccesPermission
Imports System.Security.Permissions ' FileIOPermission, FileIOPermissionAccess
Imports System.Windows ' MessageBox

Namespace SDKSample
    Public Class FileHandlingGraceful
        Public Sub Save()
            If IsPermissionGranted(New FileIOPermission(FileIOPermissionAccess.Write, "c:\newfile.txt")) Then
                ' Write to local disk
                Using stream As FileStream = File.Create("c:\newfile.txt")
                Using writer As New StreamWriter(stream)
                    writer.WriteLine("I can write to local disk.")
                End Using
                End Using
            Else
                ' Persist application-scope property to 
                ' isolated storage
                Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForApplication()
                Using stream As New IsolatedStorageFileStream("newfile.txt", FileMode.Create, storage)
                Using writer As New StreamWriter(stream)
                    writer.WriteLine("I can write to Isolated Storage")
                End Using
                End Using
            End If
        End Sub

        ' Detect whether or not this application has the requested permission
        Private Function IsPermissionGranted(ByVal requestedPermission As CodeAccessPermission) As Boolean
            Try
                ' Try and get this permission
                requestedPermission.Demand()
                Return True
            Catch
                Return False
            End Try
        End Function



...


    End Class
End Namespace
using System.IO; // File, FileStream, StreamWriter
using System.IO.IsolatedStorage; // IsolatedStorageFile
using System.Security; // CodeAccesPermission
using System.Security.Permissions; // FileIOPermission, FileIOPermissionAccess
using System.Windows; // MessageBox

namespace SDKSample
{
    public class FileHandlingGraceful
    {
        public void Save()
        {
            if (IsPermissionGranted(new FileIOPermission(FileIOPermissionAccess.Write, @"c:\newfile.txt")))
            {
                // Write to local disk
                using (FileStream stream = File.Create(@"c:\newfile.txt"))
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    writer.WriteLine("I can write to local disk.");
                }
            }
            else
            {
                // Persist application-scope property to 
                // isolated storage
                IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForApplication();
                using (IsolatedStorageFileStream stream = 
                    new IsolatedStorageFileStream("newfile.txt", FileMode.Create, storage))
                using (StreamWriter writer = new StreamWriter(stream))
                {
                    writer.WriteLine("I can write to Isolated Storage");
                }
            }
        }

        // Detect whether or not this application has the requested permission
        bool IsPermissionGranted(CodeAccessPermission requestedPermission)
        {
            try
            {
                // Try and get this permission
                requestedPermission.Demand();
                return true;
            }
            catch
            {
                return false;
            }
        }



...


    }
}

В множестве случаев найти альтернативу частичному доверию можно.

В управляемой среде, такой как интрасеть, настраиваемые управляемые объектные структуры могут быть установлены через клиентскую базу в global assembly cache (GAC). Эти библиотеки могут выполнять код, который требует полного доверия, и на них можно ссылаться из приложений, которые допускают только частичное доверие, посредством AllowPartiallyTrustedCallersAttribute (дополнительные сведения см. в разделах Безопасность (WPF) и Стратегия безопасности WPF — безопасность платформы).

Определение узла обозревателя

Использование CAS для проверки разрешений является подходящим способом, если необходимо проверять на отдельные разрешения. Однако следует отметить, что перехватывание исключений при использовании этого метода — это неотъемлемая часть нормальной работы. В общем случае не рекомендуется использовать такое поведение, это может повлиять на производительность. Вместо этого, если XAML browser application (XBAP) выполняется только в песочнице зоны Интернета, то можно использовать свойство BrowserInteropHelper.IsBrowserHosted, которое возвращает значение true для XAML browser applications (XBAPs).

ПримечаниеПримечание

Свойство IsBrowserHosted распознает только, выполняется ли приложение в браузере, оно не может определить набор разрешений, с которым выполняется приложение.

Управление разрешениями

По умолчанию XBAPs выполняется с частичным доверием (набор разрешений зоны Интернета по умолчанию). Однако, в зависимости от требований приложения, можно изменять набор разрешений по умолчанию. Например, если XBAPs запускается из локальной интрасети, он может воспользоваться преимуществом расширенного набора разрешений. См. следующую таблицу.

Таблица 3. Разрешения локальной интрасети и Интернета

Разрешение

Атрибут

Локальная интрасеть (LocalIntranet)

Internet

DNS.

Доступ к DNS-серверам

Да

Нет

Переменные среды

Прочитайте

Да

Нет

Диалоговые окна файла

Откройте .

Да

Да

Диалоговые окна файла

Unrestricted

Да

Нет

Изолированное хранилище

Изоляция сборки по пользователю

Да

Нет

Изолированное хранилище

Неизвестная изоляция

Да

Да

Изолированное хранилище

Неограниченная квота для пользователя

Да

Нет

Мультимедиа

Безопасное аудио, видео и изображения

Да

Да

Печать

Печать по умолчанию

Да

Нет

Печать

Безопасная печать

Да

Да

Отражение

Эмиссия

Да

Нет

Безопасность

Выполнение управляемого кода

Да

Да

Безопасность

Утверждение предоставленных разрешений

Да

Нет

Пользовательский интерфейс

Unrestricted

Да

Нет

Пользовательский интерфейс

Безопасные окна высокого уровня

Да

Да

Пользовательский интерфейс

Собственный буфер обмена

Да

Да

браузер

Безопасная навигация по рамкам в HTML

Да

Да

ПримечаниеПримечание

При частичном доверии действия "вырезать" и "вставить" допускаются, только если они инициированы пользователем.

Если требуется повысить уровень разрешений, нужно изменить параметры проекта и манифест приложения ClickOnce. Дополнительные сведения см. в разделе Общие сведения о приложениях браузера WPF XAML. Также могут быть полезны следующие документы.

Если ваше приложение XBAP требует полного доверия, можно использовать те же средства для предоставления запрошенных разрешений. Однако приложение XBAP получит полное доверие только в том случае, если оно установлено на локальном компьютере или запущено с локального компьютера, из интрасети или с URL-адреса, перечисленного среди доверенных или разрешенных сайтов браузера. Если приложение установлено из интрасети или с доверенного сайта, пользователь получит стандартное извещение ClickOnce, сообщающее о повышенных разрешениях. Пользователь может выбрать, продолжить или отменить установку.

Кроме того, можно использовать модель доверенного развертывания ClickOnce для полностью доверенного развертывания из любой зоны безопасности. Дополнительные сведения см. в разделах Общие сведения о развертывании доверенных приложений и Безопасность (WPF).

См. также

Основные понятия

Безопасность (WPF)

Стратегия безопасности WPF — безопасность платформы

Стратегия безопасности WPF — проектирование безопасности