Поделиться через


Более безопасный доступ к файлам и данным в Windows Forms

Платформа .NET Framework использует разрешения для защиты ресурсов и данных. Где приложение может считывать или записывать данные, зависит от разрешений, предоставленных приложению. Если приложение работает в среде с частичным доверием, возможно, у вас нет доступа к данным или вам может потребоваться изменить способ доступа к данным.

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

Заметка

По умолчанию средства, создающие развертывания ClickOnce, запрашивают полное доверие с компьютеров, на которых они выполняются. Если вы решите, что хотите воспользоваться дополнительными преимуществами безопасности, выполняя программу в режиме частичного доверия, необходимо изменить это значение по умолчанию в Visual Studio или в одном из средств Windows SDK (Mage.exe или MageUI.exe). Дополнительные сведения о безопасности Windows Forms и о том, как определить соответствующий уровень доверия для приложения, см. в разделе Безопасность в Windows Forms.

Доступ к файлам

Класс FileIOPermission управляет доступом к файлам и папкам в .NET Framework. По умолчанию система безопасности не предоставляет FileIOPermission средам частичного доверия, таким как локальная интрасетя и зоны Интернета. Однако приложение, требующее доступа к файлам, по-прежнему может функционировать в этих средах, если вы изменяете структуру приложения или используете различные методы для доступа к файлам. По умолчанию локальная зона интрасети предоставляет право иметь тот же доступ к сайту и один и тот же доступ к каталогу, подключаться к сайту своего источника и читать из своего каталога установки. По умолчанию Интернет-зоне предоставляется право только на подключение обратно к исходному сайту.

файлы User-Specified

Одним из способов борьбы с отсутствием разрешения на доступ к файлам является запрос пользователя на предоставление определенных сведений о файле с помощью класса OpenFileDialog или SaveFileDialog. Это взаимодействие с пользователем помогает обеспечить некоторую уверенность в том, что приложение не может злонамеренно загружать частные файлы или перезаписывать важные файлы. Методы OpenFile и OpenFile предоставляют доступ на чтение и запись файлов, открывая поток для файла, который указал пользователь. Методы также помогают защитить файлы пользователей, скрывая путь к файлу.

Заметка

Эти разрешения различаются в зависимости от того, находится ли ваше приложение в зоне Интернета или в зоне интрасети. Приложения зоны Интернета могут использовать только OpenFileDialog, а приложения интрасети имеют неограниченное разрешение на диалоговое окно.

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

Класс Необходимый уровень доступа
OpenFileDialog Open
SaveFileDialog Save

Заметка

Определенное разрешение не запрашивается, пока метод 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 или Windows Communication Foundation.

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

Класс RegistryPermission управляет доступом к реестру операционной системы. По умолчанию только приложения, работающие локально, могут получить доступ к реестру. RegistryPermission предоставляет приложению право на доступ к реестру; Он не гарантирует успешность доступа, так как операционная система по-прежнему обеспечивает безопасность в реестре.

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

См. также