Compartilhar via


Acesso a arquivos e dados mais seguros nos Windows Forms

Importante

Esse conteúdo só se aplica ao .NET Framework, a menos que especificado de outra forma.

O .NET Framework usa permissões para ajudar a proteger recursos e dados. Onde seu aplicativo pode ler ou gravar dados depende das permissões concedidas ao aplicativo. Quando seu aplicativo é executado em um ambiente de confiança parcial, talvez você não tenha acesso aos seus dados ou talvez precise alterar a maneira como acessa os dados.

Quando você encontra uma restrição de segurança, você tem duas opções: declarar a permissão (supondo que ela tenha sido concedida ao seu aplicativo) ou usar uma versão do recurso escrito para trabalhar em confiança parcial. As seções a seguir discutem como trabalhar com o acesso de arquivo, banco de dados e registro de aplicativos em execução em um ambiente de confiança parcial.

Observação

Por padrão, as ferramentas que geram implantações do ClickOnce configuram essas implantações para solicitar confiança total dos computadores nos quais são executadas. Se você decidir que deseja os benefícios adicionais de segurança da execução em confiança parcial, deverá alterar esse padrão no Visual Studio ou em uma das ferramentas do SDK do Windows (Mage.exe ou MageUI.exe). Para obter mais informações sobre a segurança do Windows Forms e sobre como determinar o nível de confiança apropriado para seu aplicativo, consulte Security in Windows Forms Overview.

Acesso a arquivos

A classe FileIOPermission controla o acesso ao arquivo e à pasta no .NET Framework. Por padrão, o sistema de segurança não concede o FileIOPermission a ambientes de confiança parcial, como a intranet local e as zonas da Internet. No entanto, um aplicativo que requer acesso a arquivos ainda poderá funcionar nesses ambientes se você modificar o design do aplicativo ou usar métodos diferentes para acessar arquivos. Por padrão, a zona de intranet local recebe o direito de ter o mesmo acesso ao site e ao mesmo diretório, conectar-se novamente ao site de sua origem e ler de seu diretório de instalação. Por padrão, a zona da Internet só recebe o direito de se conectar novamente ao site de sua origem.

Arquivos especificados pelo usuário

Uma maneira de lidar com a não ter permissão de acesso ao arquivo é solicitar que o usuário forneça informações de arquivo específicas usando a classe OpenFileDialog ou SaveFileDialog. Essa interação do usuário ajuda a fornecer alguma garantia de que o aplicativo não pode carregar arquivos privados mal-intencionados ou substituir arquivos importantes. Os métodos OpenFile e OpenFile fornecem acesso de leitura e gravação ao arquivo ao abrir o fluxo do arquivo especificado pelo usuário. Os métodos também ajudam a proteger o arquivo do usuário ocultando o caminho do arquivo.

Observação

Essas permissões diferem dependendo se o aplicativo está na zona da Internet ou na zona da Intranet. Aplicativos da zona da Internet só podem usar o OpenFileDialog, enquanto os aplicativos de Intranet têm permissão irrestrita de caixa de diálogo de arquivo.

A classe FileDialogPermission especifica que tipo de caixa de diálogo de arquivo seu aplicativo pode usar. A tabela a seguir mostra o valor que você deve ter para usar cada classe FileDialog.

Classe Valor de acesso necessário
OpenFileDialog Open
SaveFileDialog Save

Observação

A permissão específica não é solicitada até que o método OpenFile seja realmente chamado.

A permissão para exibir uma caixa de diálogo de arquivo não concede ao aplicativo acesso total a todos os membros das classes FileDialog, OpenFileDialoge SaveFileDialog. Para obter as permissões exatas necessárias para chamar cada método, consulte o tópico de referência desse método na documentação da biblioteca de classes do .NET Framework.

O exemplo de código a seguir usa o método OpenFile para abrir um arquivo especificado pelo usuário em um controle de RichTextBox. O exemplo requer FileDialogPermission e o valor de enumeração Open associado. O exemplo demonstra como lidar com o SecurityException para determinar se o recurso de salvamento deve ser desabilitado. Este exemplo requer que seu Form tenha um controle Button chamado ButtonOpene um controle RichTextBox chamado RtfBoxMain.

Observação

A lógica de programação para o recurso de salvamento não é mostrada no exemplo.

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;
            }
        }
    }
}

Observação

No Visual C#, certifique-se de adicionar código para habilitar o manipulador de eventos. Usando o código do exemplo anterior, o código a seguir mostra como habilitar o manipulador de eventos.this.ButtonOpen.Click += newSystem.Windows.Forms.EventHandler(this.ButtonOpen_Click);

Outros arquivos

Às vezes, você precisará ler ou gravar em arquivos que o usuário não especifica, como quando você deve persistir as configurações do aplicativo. Nas zonas de intranet e Internet locais, seu aplicativo não terá permissão para armazenar dados em um arquivo local. No entanto, seu aplicativo poderá armazenar dados no armazenamento isolado. O armazenamento isolado é um compartimento de dados abstrato (não um local de armazenamento específico) que contém um ou mais arquivos de armazenamento isolados, chamados de repositórios, que contêm os locais de diretório reais onde os dados são armazenados. Permissões de acesso a arquivos como FileIOPermission não são necessárias; em vez disso, a classe IsolatedStoragePermission controla as permissões para armazenamento isolado. Por padrão, os aplicativos que estão em execução nas zonas locais da intranet e da Internet podem armazenar dados usando o armazenamento isolado; no entanto, configurações como a cota de disco podem variar. Para obter mais informações sobre o armazenamento isolado, consulte de Armazenamento Isolado.

O exemplo a seguir usa o armazenamento isolado para gravar dados em um arquivo localizado em um repositório. O exemplo requer IsolatedStorageFilePermission e o valor de enumeração DomainIsolationByUser. O exemplo demonstra a leitura e gravação de determinados valores de propriedade do controle Button em um arquivo no armazenamento isolado. A função Read seria chamada após o início do aplicativo e a função Write seria chamada antes do fim do aplicativo. O exemplo requer que as funções Read e Write existam como membros de um Form que contém um controle Button chamado 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();
    }
}

Acesso ao banco de dados

As permissões necessárias para acessar um banco de dados variam de acordo com o provedor de banco de dados; no entanto, somente aplicativos em execução com as permissões apropriadas podem acessar um banco de dados por meio de uma conexão de dados. Para obter mais informações sobre as permissões necessárias para acessar um banco de dados, consulte Code Access Security e ADO.NET.

Se você não puder acessar diretamente um banco de dados porque deseja que seu aplicativo seja executado em confiança parcial, você pode usar um serviço Web como um meio alternativo para acessar seus dados. Um serviço Web é um software que pode ser acessado programaticamente em uma rede. Com os serviços Web, os aplicativos podem compartilhar dados entre zonas de grupo de códigos. Por padrão, os aplicativos na intranet local e nas zonas da Internet recebem o direito de acessar seus sites de origem, o que permite que eles chamem um serviço Web hospedado no mesmo servidor. Para obter mais informações, consulte Serviços Web em ASP.NET AJAX ou Windows Communication Foundation.

Acesso ao Registro

A classe RegistryPermission controla o acesso ao registro do sistema operacional. Por padrão, somente aplicativos que estão em execução localmente podem acessar o registro. RegistryPermission concede a um aplicativo o direito de tentar o acesso ao Registro; ele não garante que o acesso será bem-sucedido, pois o sistema operacional ainda impõe a segurança no registro.

Como você não pode acessar o registro sob confiança parcial, talvez seja necessário encontrar outros métodos para armazenar seus dados. Ao armazenar as configurações do aplicativo, use o armazenamento isolado em vez do registro. O armazenamento isolado também pode ser usado para armazenar outros arquivos específicos do aplicativo. Você também pode armazenar informações globais do aplicativo sobre o servidor ou site de origem, pois por padrão um aplicativo recebe o direito de acessar o site de sua origem.

Consulte também