Acceso más seguro a archivos y datos en formularios Windows Forms

.NET Framework utiliza permisos para proteger los recursos y los datos. El lugar en el que la aplicación puede escribir y leer datos dependerá de los permisos que se le concedan a la aplicación. Si la aplicación se ejecuta en un entorno de confianza parcial, puede que no tenga acceso a los datos o que deba cambiar el modo de obtener acceso a ellos.

Si encuentra una restricción de seguridad, tiene dos opciones: declarar el permiso (asumiendo que se ha concedido a la aplicación), o usar una versión de la función escrita para funcionar en confianza parcial. Las siguientes secciones explican cómo trabajar con el acceso a archivos, bases de datos y el Registro desde aplicaciones que se ejecutan en un entorno de confianza parcial.

Nota

De forma predeterminada, las herramientas que generan implementaciones ClickOnce tienen como valor predeterminado estas implementaciones para solicitar Plena confianza a los equipos en los que se ejecutan. Si decide que desea beneficiarse de las ventajas de seguridad adicionales que aporta la ejecución en confianza parcial, deberá cambiar este valor predeterminado en Visual Studio o en una de las herramientas de Kit de desarrollo de software de Windows (SDK) (Mage.exe o MageUI.exe). Para obtener más información sobre la seguridad de los formularios Windows Forms y cómo determinar el nivel de confianza adecuado para la aplicación, vea Información general sobre la seguridad en formularios Windows Forms.

Acceso a archivos

La clase FileIOPermission controla el acceso a archivos y carpetas en .NET Framework. De manera predeterminada, el sistema de seguridad no concede el permiso FileIOPermission a entornos de confianza parcial como las zonas Intranet local e Internet. Sin embargo, una aplicación que requiera el acceso a archivos puede seguir funcionando en estos entornos si se modifica el diseño de la aplicación o utiliza métodos diferentes para tener acceso a archivos. De manera predeterminada, la zona Intranet local obtiene el derecho a tener el mismo acceso de sitio y de directorio, a conectarse a su sitio de origen y a leer de su directorio de instalación. De manera predeterminada, la zona Internet, obtiene únicamente el derecho de conectarse a su sitio de origen.

Archivos especificados por el usuario

Una forma de solventar el problema de no tener permiso de acceso a los archivos es pedir al usuario que facilite información de archivos específica mediante la clase OpenFileDialog o SaveFileDialog. Esta interacción del usuario ayuda a asegurarse de que la aplicación no pueda cargar archivos privados de forma malintencionada ni sobrescribir archivos importantes. Los métodos OpenFile y OpenFile proporcionan acceso de lectura y escritura a los archivos abriendo la secuencia del archivo que especifica el usuario. Los métodos también protegen el archivo del usuario ocultando la ruta de acceso del archivo.

Nota

Estos permisos varían dependiendo de si la aplicación está en la zona Internet o Intranet. Las aplicaciones de la zona Internet sólo pueden utilizar OpenFileDialog, mientras que las aplicaciones de la zona Intranet tienen el permiso del cuadro de diálogo de archivos sin restricciones.

La clase FileDialogPermission especifica el tipo de cuadro de diálogo de archivos que puede utilizar la aplicación. En la tabla siguiente se muestra el valor que debe tener para utilizar cada clase FileDialog.

Clase

Valor de acceso necesario

OpenFileDialog

Open

SaveFileDialog

Save

Nota

El permiso necesario no se solicita hasta que se llama realmente al método OpenFile.

El permiso para ver un cuadro de diálogo de archivos no significa que la aplicación tenga acceso completo a todos los miembros de las clases FileDialog, OpenFileDialog y SaveFileDialog. Para saber exactamente los permisos necesarios para llamar a cada método, consulte el tema de referencia de ese método en la documentación de la biblioteca de clases de .NET Framework.

El ejemplo de código siguiente utiliza el método OpenFile para abrir un archivo especificado por el usuario en un control RichTextBox. El ejemplo requiere FileDialogPermission y el valor de enumeración Open asociado. El ejemplo muestra cómo controlar SecurityException para determinar si se debe deshabilitar la función Guardar. Este ejemplo requiere que Form tenga un control Button denominado ButtonOpen, y un control RichTextBox denominado RtfBoxMain.

Nota

La lógica de programación de la función Guardar no se muestra en el ejemplo.

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

Nota

En Visual C#, asegúrese de agregar código para habilitar el controlador de eventos. Mediante el código del ejemplo anterior, el código siguiente muestra cómo habilitar el controlador de eventos.this.ButtonOpen.Click += newSystem.Windows.Forms.EventHandler(this.ButtonOpen_Click);

Otros archivos

A veces tendrá que leer o escribir en archivos que el usuario no especifica, como cuando debe conservar la configuración de la aplicación. En las zonas Intranet local o Internet, la aplicación no tendrá permiso para almacenar datos en un archivo local. Sin embargo, podrá almacenar datos en una zona de almacenamiento aislado. El almacenamiento aislado es un compartimiento de datos abstracto (no una ubicación de almacenamiento específico) que contiene uno o más archivos de almacenamiento aislado, denominados zonas de almacenamiento, que incluyen las ubicaciones de directorio reales donde están almacenados los datos. No son necesarios permisos de acceso a archivos como FileIOPermission; en su lugar, la clase IsolatedStoragePermission controla los permisos de la zona de almacenamiento aislado. De manera predeterminada, las aplicaciones que se ejecutan en las zonas Intranet local e Intranet pueden almacenar datos utilizando almacenamiento aislado; sin embargo, configuraciones como la cuota del disco pueden variar. Para obtener más información acerca del almacenamiento aislado, vea Almacenamiento aislado.

El siguiente ejemplo utiliza almacenamiento aislado para escribir datos en un archivo situado en una zona de almacenamiento. El ejemplo requiere IsolatedStorageFilePermission y el valor de enumeración DomainIsolationByUser. El ejemplo muestra la lectura y escritura de determinados valores de propiedad del control Button para un archivo en una zona de almacenamiento aislado. Una vez iniciada la aplicación, se llama a la función Read y, antes de que termine la aplicación, se llama a la función Write. El ejemplo requiere que las funciones Read y Write existan como miembros de un formulario Form que contiene un control Buttondenominado 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();
    }
}

Acceso a bases de datos

Los permisos necesarios para tener acceso a una base de datos varían según el proveedor de base de datos; sin embargo, sólo las aplicaciones que se ejecuten con los permisos apropiados pueden tener acceso a una base de datos a través de una conexión de datos. Para obtener más información sobre los permisos necesarios para tener acceso a una base de datos, vea Seguridad de acceso del código y ADO.NET.

Si no puede obtener acceso directo a una base de datos porque desea ejecutar la aplicación en confianza parcial, puede utilizar un servicio Web como medio alternativo para obtener acceso a los datos. Un servicio Web es un programa de software al que se puede obtener acceso mediante programación a través de una red. Con los servicios Web, las aplicaciones pueden compartir datos entre las zonas de grupos de código. De manera predeterminada, las aplicaciones en las zonas de intranet local e Internet tienen el derecho de acceso a sus sitios de origen, lo que les permite llamar a un servicio Web hospedado en el mismo servidor. Para obtener más información, vea ASP.NET AJAX and Web Services o Windows Communication Foundation.

Acceso al Registro

La clase RegistryPermission controla el acceso al Registro del sistema operativo. De manera predeterminada, solo las aplicaciones que se ejecutan localmente pueden obtener acceso al Registro. RegistryPermission solo concede a una aplicación el derecho de intentar obtener acceso al Registro; no garantiza que logre el acceso porque el sistema operativo aún impone la seguridad en el Registro.

Dado que no puede tener acceso al Registro bajo la confianza parcial, puede que deba encontrar otros métodos de almacenar los datos. Cuando almacene parámetros de configuración de la aplicación, utilice el almacenamiento aislado en lugar del Registro. El almacenamiento aislado se puede utilizar también para almacenar otros archivos específicos de la aplicación. También puede almacenar información global de la aplicación sobre el servidor o sitio de origen, puesto que, de manera predeterminada, una aplicación obtiene el derecho de acceso a su sitio de origen.

Vea también

Referencia

Mage.exe (Herramienta de generación y edición de manifiestos)

MageUI.exe (Herramienta de generación y edición de manifiestos, cliente gráfico)

Conceptos

Impresión más segura en formularios Windows Forms

Consideraciones de seguridad adicionales en formularios Windows Forms

Información general sobre la seguridad en formularios Windows Forms

Otros recursos

Seguridad en los formularios Windows Forms