Seguridad de confianza parcial de WPF

En general, las aplicaciones de Internet deben tener restringido el acceso directo a los recursos del sistema críticos, a fin de evitar los daños malintencionados. De manera predeterminada, HTML y los lenguajes de script de cliente no pueden tener acceso a los recursos del sistema críticos. Dado que las aplicaciones Windows Presentation Foundation (WPF) hospedadas por el explorador se pueden iniciar desde el explorador, deben cumplir un conjunto de restricciones similar. Para exigir estas restricciones, WPF se basa en Code Access Security (CAS) y ClickOnce (consulte Estrategia de seguridad de WPF: Seguridad de plataforma). De manera predeterminada, las aplicaciones hospedadas por el explorador solicitan el conjunto de permisos Zona de Internet de CAS, con independencia de si se inician desde Internet, desde la intranet local o desde el equipo local. Se dice que las aplicaciones que se ejecutan con menos permisos que el conjunto completo de permisos se están ejecutando con confianza parcial.

WPF proporciona gran variedad de características de compatibilidad para asegurarse de que se pueda utilizar tanta funcionalidad como sea posible sin riesgo alguno en confianza parcial y, junto con CAS, proporciona la compatibilidad adicional para la programación de confianza parcial.

Este tema contiene las siguientes secciones:

  • Compatibilidad con la confianza parcial de las características de WPF

  • Programación de la confianza parcial

  • Administrar permisos

Compatibilidad con la confianza parcial de las características de WPF

En la tabla siguiente se muestra una lista de las características generales de Windows Presentation Foundation (WPF) que resulta seguro utilizar dentro de los límites del conjunto de permisos Zona de Internet.

Tabla 1: Características de WPF seguras con confianza parcial

Área de la característica

Característica

General

Explorador (Ventana)

Acceso al sitio de origen

Almacenamiento aislado (límite de 512 KB)

Proveedores de automatización de la IU

Comandos

Editores de métodos de entrada (IME)

Lápiz óptico de Tablet PC y entradas de lápiz

Métodos de arrastrar y colocar simulados mediante eventos Capture y Move del mouse.

OpenFileDialog

Deserialización XAML (mediante XamlReader.Load)

Integración en web

Cuadro de diálogo de descarga del explorador

Navegación de nivel superior iniciada por el usuario

mailto:links

Parámetros de identificador uniforme de recursos

HTTPWebRequest

Contenido WPF hospedado en IFRAME

Hospedar páginas HTML del mismo sitio mediante Frame

Hospedar páginas HTML del mismo sitio mediante WebBrowser

Servicios Web (ASMX)

Servicios Web (mediante Windows Communication Foundation)

Scripting

Modelo de objetos de documento

Elementos visuales

2D y 3D

Animación

Multimedia (sitio de origen y entre dominios)

Imágenes/audio/vídeo

Lectura

Documentos dinámicos

Documentos XPS

Fuentes incrustadas y del sistema

Fuentes CFF y TrueType

Edición

Revisión ortográfica

RichTextBox

Texto simple y compatibilidad de portapapeles de entradas de lápiz

Acción de pegar iniciada por el usuario

Copiar contenido seleccionado

Controles

Controles generales

En esta tabla se muestran las características de WPF de alto nivel. Para obtener más información detallada, en Windows Software Development Kit (SDK) se documentan los permisos que necesita cada miembro en WPF. Asimismo, las características siguientes ofrecen información más detallada relativa a la ejecución de la confianza parcial, incluidas algunas consideraciones especiales.

En la tabla siguiente se describen las características de WPF que no es seguro ejecutar dentro de los límites del conjunto de permisos Zona de Internet.

Tabla 2: Características de WPF no seguras con confianza parcial

Área de la característica

Característica

General

Ventana (ventanas y cuadros de diálogo definidos por la aplicación)

SaveFileDialog

Sistema de archivos

Acceso al Registro

Arrastrar y colocar

Serialización XAML (mediante XamlWriter.Save)

Clientes de automatización de la interfaz de usuario

Acceso a la ventana de origen (HwndHost)

Compatibilidad plena con voz

Interoperabilidad con formularios Windows Forms

Elementos visuales

Efectos de mapa de bits

Codificación de imágenes

Edición

Portapapeles de formato de texto enriquecido

Compatibilidad plena con XAML

Programación de la confianza parcial

Para aplicaciones XBAP, el código que supera el conjunto de permisos predeterminado tendrá un comportamiento diferente según la zona de seguridad. En algunos casos, el usuario recibirá una advertencia cuando intente instalarla. El usuario puede continuar o cancelar la instalación. En la tabla siguiente se describe el comportamiento de la aplicación para cada zona de seguridad y lo que tiene que hacer para que la aplicación reciba plena confianza.

Zona de seguridad

Behavior

Obtener plena confianza

Equipo local

Plena confianza automática

No se requiere ninguna acción.

Intranet y sitios de confianza

Solicitar plena confianza

Firmar la aplicación XBAP con un certificado para que el usuario vea el origen en el indicador.

Internet

Se produce un error "Confianza no concedida"

Firmar la aplicación XBAP con un certificado.

NotaNota

El comportamiento descrito en la tabla anterior es para las aplicaciones XBAP de plena confianza que no siguen el modelo de implementación de confianza de ClickOnce.

En general, es probable que el código que puede superar los permisos concedidos sea código común que se comparte entre las aplicaciones independientes y hospedadas por explorador. CAS y WPF proporcionan varias técnicas para administrar este escenario.

Detectar permisos mediante CAS

En algunas situaciones, es posible que el código compartido en los ensamblados de bibliotecas se utilice en aplicaciones independientes y XBAPs. En estos casos, el código puede ejecutar funcionalidad que podría requerir más permisos de los permitidos por el conjunto de permisos de la aplicación. La aplicación puede detectar si tiene un permiso determinado o no mediante la seguridad de Microsoft .NET Framework. En particular, puede comprobar si tiene un permiso concreto llamando al método Demand en la instancia del permiso deseado. Esto se muestra en el ejemplo siguiente, que contiene código que consulta si tiene la capacidad de guardar un archivo en el disco local:


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



...


    }
}

Si una aplicación no tiene el permiso deseado, la llamada a Demand provocará una excepción de seguridad. De lo contrario, se ha concedido el permiso. IsPermissionGranted encapsula este comportamiento y devuelve true o false, según corresponda.

Degradación correcta de la funcionalidad

Poder detectar si el código tiene permiso para lo que necesita hacer es interesante para el código que se puede ejecutar desde zonas diferentes. Aunque detectar la zona es necesario, resulta mucho mejor proporcionar una alternativa al usuario, si es posible. Por ejemplo, una aplicación de plena confianza suele permitir al usuario crear los archivos que desee en cualquier lugar, mientras que una aplicación de confianza parcial sólo permite crearlos en almacenamiento aislado. Si el código para crear un archivo existe en un ensamblado compartido por aplicaciones de plena confianza (independientes) y de confianza parcial (hospedadas por explorador), y ambas aplicaciones desean que los usuarios puedan crear archivos, el código compartido debería detectar si se ejecuta con confianza parcial o plena antes de crear un archivo en la ubicación adecuada. En el código siguiente se muestran ambas operaciones.


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



...


    }
}

En muchos casos, debe existir una alternativa de confianza parcial.

En un entorno controlado, como una intranet, los marcos de trabajo administrados personalizados se pueden instalar en toda la base de clientes en global assembly cache (GAC). Estas bibliotecas pueden ejecutar código que requiere plena confianza y se puede hacer referencia a ellas en las aplicaciones que solo tienen confianza parcial mediante AllowPartiallyTrustedCallersAttribute (para obtener más información, vea Seguridad (WPF) y Estrategia de seguridad de WPF: Seguridad de plataforma).

Detección del host del explorador

Utilizar CAS para comprobar los permisos es una técnica conveniente cuando se necesita comprobar los permisos uno a uno. Sin embargo, esta técnica depende de que se detecten las excepciones como parte de procesamiento normal, algo que, en general, no se recomienda, y que puede dar lugar a problemas de rendimiento. En su lugar, si XAML browser application (XBAP) solamente se ejecuta dentro del espacio aislado de la Zona de Internet, puede usar la propiedad BrowserInteropHelper.IsBrowserHosted, que devuelve true para XAML browser applications (XBAPs).

NotaNota

IsBrowserHosted únicamente distingue si una aplicación se está ejecutando en un explorador, no detecta con qué conjunto de permisos se está ejecutando.

Administrar permisos

De forma predeterminada, las XBAPs se ejecutan con confianza parcial (conjunto de permisos de Zona de Internet predeterminado). Sin embargo, dependiendo de los requisitos de la aplicación, es posible cambiar el conjunto de permisos predeterminado. Por ejemplo, si se inician XBAPs desde una intranet local, puede aprovechar un conjunto de permisos mayor, que se muestra en la tabla siguiente.

Tabla 3: Permisos de intranet local y de Internet

Permiso

Atributo

LocalIntranet

Internet

DNS

Tener acceso a los servidores DNS

No

Variables de entorno

Lectura

No

Cuadros de diálogo de archivo

Abra .

Cuadros de diálogo de archivo

Sin restricciones

No

Almacenamiento aislado

Aislamiento de ensamblados por usuario

No

Almacenamiento aislado

Aislamiento desconocido

Almacenamiento aislado

Cuota de usuario ilimitada

No

Multimedia

Audio, vídeo e imágenes seguros

Impresión

Impresión predeterminada

No

Impresión

Impresión segura

Reflexión

Emisión

No

Seguridad

Ejecución de código administrado

Seguridad

Declaración de permisos concedidos

No

Interfaz de usuario

Sin restricciones

No

Interfaz de usuario

Ventanas de nivel superior seguras

Interfaz de usuario

Portapapeles propio

Web Browser

Navegación de marcos segura en HTML

NotaNota

Solo se permite cortar y pegar en la confianza parcial cuando sea iniciado por el usuario.

Si necesita aumentar los permisos, es preciso modificar la configuración del proyecto y el manifiesto de la aplicación ClickOnce. Para obtener más información, vea Información general sobre las aplicaciones de explorador XAML de WPF. Los siguientes documentos también pueden ser útiles.

Si XBAP requiere plena confianza, puede utilizar las mismas herramientas para aumentar los permisos solicitados, Aunque una XBAP solo recibirá plena confianza si se instala e inicia en el equipo local, la intranet o una dirección URL incluida en la lista de sitios permitidos o de confianza del explorador. Si la aplicación se instala desde la intranet o un sitio de confianza, el usuario recibirá el mensaje estándar de ClickOnce para notificarle los permisos elevados. El usuario puede continuar o cancelar la instalación.

Como alternativa, se puede utilizar el modelo de implementación de confianza de ClickOnce para realizar una implementación de plena confianza desde una zona de seguridad. Para obtener más información, vea Información general sobre la implementación de aplicaciones de confianza y Seguridad (WPF).

Vea también

Conceptos

Seguridad (WPF)

Estrategia de seguridad de WPF: Seguridad de plataforma

Estrategia de seguridad de WPF: Ingeniería de seguridad