Более безопасный доступ к файлам и данным в Windows Forms
.NET Framework использует разрешения для защиты ресурсов и данных. В зависимости от полученных разрешений приложение может выполнять чтение и запись данных. Если приложение выполняется среде c частичным доверием, то, возможно, доступ к данным будет запрещен или необходимо будет изменить способ доступа к данным.
При возникновении ограничений системы безопасности, имеются две возможности: подтверждение разрешения (предполагая, что оно было предоставлено приложению) или использование специальной версии кода, написанной для работы в условиях частичного доверия. В следующих разделах обсуждаются способы доступа к файлам, базам данных и реестру из приложений, работающих в среде с частичным доверием.
Примечание
По умолчанию средства, развертывающие ClickOnce, настраивают экземпляры этой среды таким образом, чтобы требовать полного доверия от компьютеров, на которых они запущены.Если необходимо воспользоваться средствами обеспечения повышенной безопасности при выполнении в среде с частичным доверием, следует изменить стандартное поведение либо в Visual Studio, либо в одном из средств Пакет средств разработки программного обеспечения (SDK) для Windows (Mage.exe или MageUI.exe).Дополнительные сведения о системе безопасности Windows Forms и о том, как определить оптимальный уровень доверия для приложения, см. в разделе Общие сведения о безопасности в Windows Forms.
Доступ к файлам
Класс FileIOPermission управляет доступом к файлам и папкам в .NET Framework. По умолчанию система безопасности не предоставляет разрешение FileIOPermission в средах с частичным доверием, таких как зоны локальной интрасети или Интернета. Однако приложение, которому требуется доступ к файлам, может работать в таких средах, если изменить структуру приложения или использовать другие методы доступа к файлам. По умолчанию зоне локальной интрасети предоставляется право на доступ к тому же узлу и к той же папке, чтобы подключаться к исходному узлу и считывать файлы из папки установки. Приложениям в зоне Интернета по умолчанию разрешено подключаться только к исходному узлу.
Файлы, определенные пользователем
Одним из способов разрешения проблем, связанных с отсутствием разрешения на доступ к файлам, является запрос у пользователя предоставления сведений о конкретном файле с помощью класса OpenFileDialog или SaveFileDialog. Взаимодействие с пользователем помогает получить некоторую уверенность в том, что приложение не сможет злоумышленно загрузить личные файлы или перезаписать важные файлы. Методы OpenFile и OpenFile предоставляют доступ на чтение и запись файла, открывая файловый поток для файла, указанного пользователем. Эти методы также помогают защитить файл пользователя, скрывая путь к файлу.
Примечание
Данные разрешения зависят от того, в какой зоне находится приложение: интрасеть или Интернет.Приложения зоны Интернета могут использовать только класс OpenFileDialog, тогда как приложения интрасети имеют неограниченное разрешение на файловые диалоговые окна.
Класс FileDialogPermission указывает какой тип диалогового окна может использовать приложение. В следующей таблице приведены значения, которые необходимо использовать для каждого класса FileDialog.
Класс |
Необходимое значение для доступа |
---|---|
Примечание
Конкретные разрешения не запрашиваются до тех пор, пока не будет вызван метод OpenFile.
Разрешение на отображение файлового диалогового окна не дает приложению полный доступ ко всем членам классов FileDialog, OpenFileDialog и SaveFileDialog. Точные разрешения, требуемые для вызова каждого метода, приведены в разделах, относящихся к этому методу в документации по библиотеке классов .NET Framework.
В следующем примере кода метод OpenFile используется для открытия указанного пользователем файла в элементе управления RichTextBox. Для этого пример требуется класс FileDialogPermission и связанное с ним значение перечисления Open. В примере показано, как обрабатывать исключение SecurityException, чтобы определить, нужно ли отключить функцию сохранения. В этом примере требуется, чтобы форма Form содержала элемент управления Button с именем ButtonOpen и элемент управления RichTextBox с именем RtfBoxMain.
Примечание
Программная логика для функции сохранения в примере не представлена.
Private Sub ButtonOpen_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles ButtonOpen.Click
Dim editingFileName as String = ""
Dim saveAllowed As Boolean = True
' Displays the OpenFileDialog.
If (OpenFileDialog1.ShowDialog() = DialogResult.OK) Then
Dim userStream as System.IO.Stream
Try
' Opens the file stream for the file selected by the user.
userStream =OpenFileDialog1.OpenFile()
Me.RtfBoxMain.LoadFile(userStream, _
RichTextBoxStreamType.PlainText)
Finally
userStream.Close()
End Try
' Tries to get the file name selected by the user.
' Failure means that the application does not have
' unrestricted permission to the file.
Try
editingFileName = OpenFileDialog1.FileName
Catch ex As Exception
If TypeOf ex Is System.Security.SecurityException Then
' The application does not have unrestricted permission
' to the file so the save feature will be disabled.
saveAllowed = False
Else
Throw ex
End If
End Try
End If
End Sub
private void ButtonOpen_Click(object sender, System.EventArgs e)
{
String editingFileName = "";
Boolean saveAllowed = true;
// Displays the OpenFileDialog.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
// Opens the file stream for the file selected by the user.
using (System.IO.Stream userStream = openFileDialog1.OpenFile())
{
this.RtfBoxMain.LoadFile(userStream,
RichTextBoxStreamType.PlainText);
userStream.Close();
}
// Tries to get the file name selected by the user.
// Failure means that the application does not have
// unrestricted permission to the file.
try
{
editingFileName = openFileDialog1.FileName;
}
catch (Exception ex)
{
if (ex is System.Security.SecurityException)
{
// The application does not have unrestricted permission
// to the file so the save feature will be disabled.
saveAllowed = false;
}
else
{
throw ex;
}
}
}
}
Примечание
В Visual C# убедитесь, что код для включения обработчика событий добавлен.Следующий код показывает, как с помощью кода из предыдущего примера включить обработчик событий.this.ButtonOpen.Click += newSystem.Windows.Forms.EventHandler(this.ButtonOpen_Click);
Другие файлы
Иногда необходимо считывать или записывать файлы, которые не указываются пользователем, например если требуется сохранить параметры приложения. В зонах локальной интрасети и Интернета приложение не имеет разрешения сохранять данные в локальном файле. Тем не менее, приложение может сохранять данные в изолированном хранилище. Изолированное хранилище — это абстрактный отсек данных (а не конкретное хранилище), содержащий один или несколько изолированных файлов хранения, называемых хранилищами, которые содержат сведения о действительных папках расположения данных. Разрешения доступа к файлам, такие как FileIOPermission, не обязательны; вместо этого класс IsolatedStoragePermission управляет разрешениями для изолированного хранилища. По умолчанию приложения, запущенные в зонах локальной интрасети и Интернета, могут хранить данные с помощью изолированного хранилища; однако такие параметры, как дисковая квота, могут меняться. Дополнительные сведения об изолированном хранилище см. в разделе Изолированное хранилище.
В следующем примере для записи данных в файл, расположенный в хранилище, используется изолированное хранилище. Для этого примера требуется разрешение IsolatedStorageFilePermission и значение перечисления DomainIsolationByUser. В примере демонстрируется чтение и запись определенных значений свойств элемента управления Button в файл в изолированном хранилище. Функция Read может быть вызвана после запуска приложения, а функция Write — до окончания работы приложения. В этом примере требуется существования функций Read и Write как членов формы Form, которая содержит элемент управления Buttonс именем MainButton.
' Reads the button options from the isolated storage. Uses Default values
' for the button if the options file does not exist.
Public Sub Read()
Dim isoStore As System.IO.IsolatedStorage.IsolatedStorageFile = _
System.IO.IsolatedStorage.IsolatedStorageFile. _
GetUserStoreForDomain()
Dim filename As String = "options.txt"
Try
' Checks to see if the options.txt file exists.
If (isoStore.GetFileNames(filename).GetLength(0) <> 0) Then
' Opens the file because it exists.
Dim isos As New System.IO.IsolatedStorage.IsolatedStorageFileStream _
(filename, IO.FileMode.Open,isoStore)
Dim reader as System.IO.StreamReader
Try
reader = new System.IO.StreamReader(isos)
' Reads the values stored.
Dim converter As System.ComponentModel.TypeConverter
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Color))
Me.MainButton.BackColor = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Color)
me.MainButton.ForeColor = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Color)
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Font))
me.MainButton.Font = _
CType(converter.ConvertFromString _
(reader.ReadLine()), Font)
Catch ex As Exception
Debug.WriteLine("Cannot read options " + _
ex.ToString())
Finally
reader.Close()
End Try
End If
Catch ex As Exception
Debug.WriteLine("Cannot read options " + ex.ToString())
End Try
End Sub
' Writes the button options to the isolated storage.
Public Sub Write()
Dim isoStore As System.IO.IsolatedStorage.IsolatedStorageFile = _
System.IO.IsolatedStorage.IsolatedStorageFile. _
GetUserStoreForDomain()
Dim filename As String = "options.txt"
Try
' Checks if the file exists, and if it does, tries to delete it.
If (isoStore.GetFileNames(filename).GetLength(0) <> 0) Then
isoStore.DeleteFile(filename)
End If
Catch ex As Exception
Debug.WriteLine("Cannot delete file " + ex.ToString())
End Try
' Creates the options.txt file and writes the button options to it.
Dim writer as System.IO.StreamWriter
Try
Dim isos As New System.IO.IsolatedStorage.IsolatedStorageFileStream _
(filename, IO.FileMode.CreateNew, isoStore)
writer = New System.IO.StreamWriter(isos)
Dim converter As System.ComponentModel.TypeConverter
converter = System.ComponentModel.TypeDescriptor.GetConverter _
(GetType(Color))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.BackColor))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.ForeColor))
converter = System.ComponentModel TypeDescriptor.GetConverter _
(GetType(Font))
writer.WriteLine(converter.ConvertToString( _
Me.MainButton.Font))
Catch ex as Exception
Debug.WriteLine("Cannot write options " + ex.ToString())
Finally
writer.Close()
End Try
End Sub
// Reads the button options from the isolated storage. Uses default values
// for the button if the options file does not exist.
public void Read()
{
System.IO.IsolatedStorage.IsolatedStorageFile isoStore =
System.IO.IsolatedStorage.IsolatedStorageFile.
GetUserStoreForDomain();
string filename = "options.txt";
try
{
// Checks to see if the options.txt file exists.
if (isoStore.GetFileNames(filename).GetLength(0) != 0)
{
// Opens the file because it exists.
System.IO.IsolatedStorage.IsolatedStorageFileStream isos =
new System.IO.IsolatedStorage.IsolatedStorageFileStream
(filename, System.IO.FileMode.Open,isoStore);
System.IO.StreamReader reader = null;
try
{
reader = new System.IO.StreamReader(isos);
// Reads the values stored.
TypeConverter converter ;
converter = TypeDescriptor.GetConverter(typeof(Color));
this.MainButton.BackColor =
(Color)(converter.ConvertFromString(reader.ReadLine()));
this.MainButton.ForeColor =
(Color)(converter.ConvertFromString(reader.ReadLine()));
converter = TypeDescriptor.GetConverter(typeof(Font));
this.MainButton.Font =
(Font)(converter.ConvertFromString(reader.ReadLine()));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot read options " + ex.ToString());
}
finally
{
reader.Close();
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot read options " + ex.ToString());
}
}
// Writes the button options to the isolated storage.
public void Write()
{
System.IO.IsolatedStorage.IsolatedStorageFile isoStore =
System.IO.IsolatedStorage.IsolatedStorageFile.
GetUserStoreForDomain();
string filename = "options.txt";
try
{
// Checks if the file exists and, if it does, tries to delete it.
if (isoStore.GetFileNames(filename).GetLength(0) != 0)
{
isoStore.DeleteFile(filename);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot delete file " + ex.ToString());
}
// Creates the options file and writes the button options to it.
System.IO.StreamWriter writer = null;
try
{
System.IO.IsolatedStorage.IsolatedStorageFileStream isos = new
System.IO.IsolatedStorage.IsolatedStorageFileStream(filename,
System.IO.FileMode.CreateNew,isoStore);
writer = new System.IO.StreamWriter(isos);
TypeConverter converter ;
converter = TypeDescriptor.GetConverter(typeof(Color));
writer.WriteLine(converter.ConvertToString(
this.MainButton.BackColor));
writer.WriteLine(converter.ConvertToString(
this.MainButton.ForeColor));
converter = TypeDescriptor.GetConverter(typeof(Font));
writer.WriteLine(converter.ConvertToString(
this.MainButton.Font));
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine
("Cannot write options " + ex.ToString());
}
finally
{
writer.Close();
}
}
Доступ к базе данных
Разрешения, необходимые для доступа к базе данных различаются в зависимости от поставщика базы данных; однако только приложения с соответствующими разрешениями могут получить доступ к базе данных через подключение данных. Дополнительные сведения о разрешениях, необходимых для доступа к базе данных, см. в разделе Управление доступом для кода и ADO.NET.
Если невозможно получить доступ к базе данных непосредственно, так как требуется, чтобы приложение работало в среде с частичным доверием, можно использовать веб-службу как альтернативное средство доступа к данным. Веб-служба — это программа, доступ к которой можно получить программными средствами по сети. При помощи веб-служб приложения могут совместно использовать данные из различных зон групп кода. По умолчанию приложения в зонах локальной интрасети и Интернета получают право на доступ к исходным сайтам, что позволяет им вызывать веб-службы, размещенные на том же сервере. Дополнительные сведения см. в разделах ASP.NET AJAX and Web Services или Windows Communication Foundation.
Доступ к реестру
Класс RegistryPermission управляет доступом к реестру операционной системы. По умолчанию доступ к реестру может получить только локально запущенное приложение. RegistryPermission только предоставляет приложению право попытаться получить доступ к реестру, но не гарантирует, что доступ будет успешно получен, потому что операционная система принудительно обеспечивает безопасность реестра.
Поскольку в среде с частичным доверием доступ к реестру получить не удается, необходимо найти другие способы хранения данных. Для хранения параметров приложения используйте вместо реестра изолированное хранилище. Изолированное сохранение можно использовать также для хранения файлов, относящихся к приложению. Можно хранить общие сведения приложения о сервере или исходном узле, поскольку по умолчанию приложение имеет право на доступ к исходному узлу.
См. также
Ссылки
Mage.exe (средство создания и редактирования манифеста)
MageUI.exe (средство создания и редактирования манифестов, графический клиент)
Основные понятия
Более безопасная печать в Windows Forms
Дополнительные вопросы безопасности в формах Windows Forms
Общие сведения о безопасности в Windows Forms