jueves, 25 de mayo de 2006

Impresiones Iniciales de Windows Vista Beta 2

Bueno, ayer estuve hasta las 4 a.m. instalando el Beta 2 de Windows Vista. Lo veo mucho mejor que la versión anterior que había probado (el CTP de Febrero).

- Este ya lo pude instalar en mi Dell XPS600 con RAID 0 (NVIDIA ya sacó los drivers necesarios).
- El performance es mucho mejor.
- La interfaz se ve mucho más acabada.
- El sidebar funciona bien y trae más gadgets.
- La instalación es más rápida (ayer instalé en una partición limpia).

También instalé el Beta 2 de Office 2007 pero he jugado poco con el. El Outlook al menos jaló bien. Lo demás no lo he visto, pero de un primer vistazo a Excel veo que no me va a ser tan fácil acostumbrarme a la nueva interfaz.

Me gustó tanto que hoy decidí hacer un respaldo de mi partición de Windows XP e intentar instalar Vista sobre XP. En este momento está aparentemente detenido en Gathering Files (99%) pero no se ha caído, así que le voy a tener paciencia un rato más.

Aventuras en un Framework de Seguridad en .NET (3)

En esta ocasión vamos a hablar del método Authorize (tomado del Microsoft Enterprise Library 2.o) y de los ajustes que son necesarios para llevar la funcionalidad de nuestro UserControl al .NET Compact Framework para soportar dispositivos móviles.

El método Authorize es el siguiente:


///
/// Evaluates the specified authority against the specified context.
///

/// Must be an object.
/// The name of the rule to evaluate.
/// true if the expression evaluates to true,
/// otherwise false.

private bool Authorize(IPrincipal principal, string c, out Behavior b, out bool Evaluated)
{
Evaluated = false;
if (principal == null) throw new ArgumentNullException("principal");
if (c == null ) throw new ArgumentNullException("Control");
BooleanExpression booleanExpression = GetParsedControlExpression(m_strFormName,
c, out b, out Evaluated);

if (booleanExpression == null)
{
Evaluated = false;
return true;
}
bool result = booleanExpression.Evaluate(principal);
return result;
}

La clave aquí es la llamada a booleanExpression.Evaluate(principal) que es un muy útil evaluador de expresiones que viene incluído en el Enterprise Library 2.0. Esta función utiliza el método IsInRole del Principal para evaluar la expresión conforme a las reglas que se le pasan en la cadena c.

Otro aspecto que buscamos en esta librería, es que se pueda utilizar también en el .NET Compact Framework 2.0.

Para esto, la estrategia tiene algunos cambios con respecto al control de escritorio. Los principales son:

1. La evaluación de las expresiones no la hace el dispositivo móvil, sino un servidor a través de un servicio web. esto se debe a que en el caso de un dispositivo móvil, debemos de ser cuidadosos con el consumo de recursos o el desempeño de nuestra aplicación podría verse severamente afectado.

2. Los metodos que nos permiten utilizar reflection para ver que función nos está llamando en AuthorizeMethod no existen en el Compact Framework, por lo que necesitamos pasar explícitamente el nombre del método.

miércoles, 3 de mayo de 2006

Aventuras en un Framework de Seguridad en .NET (2)

En esta ocasión voy a analizar algunos elementos que se requieren para satisfacer los puntos 1 y 2 de mis requerimientos planteados anteriormente.

Recordemos brevemente:

1. Que los programadores puedan implementar la seguridad sin programar.
2. Que podamos hacer visibles/invisibles o habilitados/deshabilitados elementos de la IU de manera totalmente declarativa, ya sea en una BD o en XML.

Para satisfacer el punto 1, podemos desarrollar un control gráfico, que simplemente se arrastre con drag and drop a cada forma del proyecto en la que se desea tener seguridad (aquí estamos hablando de Windows Forms).

Mi primera intención fue crear un componente no gráfico (heredando de System.Windows.Forms.Component) ya que este implementador de seguridad no requiere de una interfaz gráfica para si mismo. Sin embargo, me enfrenté a la dificultad de que un componente de este tipo no puede determinar en tiempo de ejecución a que forma pertenece. Existen algunos trucos para determinar esto en tiempo de diseño pero no me gustaron ya que quedaría una solución frágil ante renombramientos y cambios de ese tipo.

Por lo tanto opté por desarrollar un control (heredando de System.Windows.Forms.UserControl) que se vuelve invisible en tiempo de ejecución. No tan elegante como quisiera pero funcional. Se parece al viejo timer de VB6, ¿se acuerdan?

Para que este control pueda encargarse de configurar la interfaz en tiempo de ejecución, necesita analizar al correr todos los elementos gráficos de la forma e ir encendiendo/apagando/habilitando/deshabilitando los elementos de la IU conforme a las reglas de seguridad declaradas. Sin embargo, no es suficiente con hacer esto al cargar la forma. ¿Qué pasa si el código del programador enciende o habilita programáticamente un control que no debería para el usuario firmado? Por esta razón es necesario también establecer manejadores de los eventos OnEnabledChanged y OnVisibleChanged de los controles bloqueados para poder levantar una excepción de seguridad en caso necesario.

El código que itera sobre los controles se ve más o menos así:

private void AuthorizeControls( Control main)
{
IPrincipal iprin = Thread.CurrentPrincipal;
Behavior b;
bool bEvaluated = false;
foreach (Control c in main.Controls)
{


if (c.Controls.Count > 0)
AuthorizeControls(c);


if (!Authorize(iprin, c.Name, out b, out bEvaluated))
{
switch (b)
{
case Behavior.Enabled:
c.Enabled = false;
c.EnabledChanged += new EventHandler(c_EnabledChanged);
break;
case Behavior.Visible:
c.Visible = false;
c.VisibleChanged += new EventHandler(c_VisibleChanged);
break;
case Behavior.Both:
c.Enabled = false;
c.EnabledChanged += new EventHandler(c_EnabledChanged);
c.Visible = false;
c.VisibleChanged += new EventHandler(c_VisibleChanged);
break;
}
}
else
{
if (bEvaluated)
{
switch (b)
{
case Behavior.Enabled:
c.Enabled = true;
c.EnabledChanged -= new EventHandler(c_EnabledChanged);
break;
case Behavior.Visible:
c.Visible = true;
c.VisibleChanged -= new EventHandler(c_VisibleChanged);
break;
case Behavior.Both:
c.Enabled = true;
c.EnabledChanged -= new EventHandler(c_EnabledChanged);
c.Visible = true;
c.VisibleChanged -= new EventHandler(c_VisibleChanged);
break;
}
}
}
}
}

void c_VisibleChanged(object sender, EventArgs e)
{
throw new System.Security.SecurityException
(m_strUISecurityException);
}

void c_EnabledChanged(object sender, EventArgs e)
{
throw new System.Security.SecurityException
(m_strUISecurityException);
}

Este código está un poco simplificado. Para completarlo hay que contemplar la posibilidad de manejar controles que viven dentro de objetos ToolStrip. Desafortunadamente estos contenedores no tienen a sus controles "hijos" en una colección Controls sino en Items por lo que hay que considerar esa diferencia también.

En la siguiente actualización voy a hablar de como se autorizan los controles (como funciona el método Authorize.