Autorizando manejadores “virtuales”

marzo 26, 2009
By

Recientemente me di a la tarea de implementar un manejador HTTP (HttpHandler) para una aplicación ASP.NET. Para no agobiarlos con los detalles de la implementación de ese handler solo les diré que su función principal era la ejecución de un proceso en el servidor Web. Obviamente no quería que cualquiera pudiera llegar y pedir la URL del manejador, con lo cual se ejecutaría el proceso antes mencionado. En mi escenario la aplicación Web tenía habilitada la autenticación por formulario por lo cual pensé en usar el mismo mecanismo para restringir el acceso al manejador y aprovechar las bondades y la simpleza de la autorización basada en la URL que proporciona ASP.NET.

Para ilustrar un poco las cosas, mi manejador sería algo así (no tan inocuo, claro ;-) :

class RunCmdHandler:System.Web.IHttpHandler
{
    public bool IsReusable
    {
        get { return false; }
    }

    public void ProcessRequest(HttpContext context)
    {
        context.Response.Write("Hello People... I'm here.");
    }
}

Y el código a colocar en el fichero de configuración web.config, para registrar el manejador y definir los permisos, el siguiente:

<configuration>
  <system.web>
    <authentication mode="Forms" />
    <httpHandlers>
	<add verb="*" path="RunCmd.axd" type="RunCmdHandler"/>
    </httpHandlers>
  </system.web>

  <location path="RunCmd.axd">
    <system.web>
      <authorization>
         <allow roles="Administrators" />
         <deny users="*" />
      </authorization>
    </system.web>
  </location>
</configuration>

El código y la configuración anteriores permiten acceder a la funcionalidad brindada por el manejador a través de la URL http://[server_name]/[app_virtual_path]/RunCmd.axd. La sección location del web.config permite restringir el acceso de modo que solo los usuarios en el rol Administrators puedan ejecutar el manejador.

Y esto iba bien, hasta que…

…la curiosidad me hizo probar la siguiente URL:

http://[server_name]/[app_virtual_path]/[some_path]/RunCmd.axd

¿Qué creen que ocurrió? ¿Qué debería haber ocurrido? ¿Qué hubiera querido que ocurriese?

Lo que ocurrió podrán imaginarlo, y es la razón pricipal que me motivó a escribir este post: el manejador se ejecutó sin que las reglas de autorización definidas en el web.config se tuvieran en cuenta. A primera vista esto pudiera verse como un bug, pero lo cierto es que según el ciclo de vida de un pedido ASP.NET, este comportamiento es correcto, aunque en mi caso indeseado.

IIS al recibir un pedido de un fichero asociado con ASP.NET, trasfiere el pedido directamente a ASP.NET, para que éste se encargue de su procesamiento. Tal es el caso del manejador RunCmd.axd. IIS no verifica que el fichero exista, sino que pasa el pedido a ASP.NET para que lo procese. ASP.NET por su parte tampoco controla que el fichero exista físicamente, pues se trata de un manejador “virtual”, y por tanto siempre lo procesa, usando el tipo definido en la sección httpHandlers del web.config.

A partir de lo anterior concluí que la autorización de ASP.NET basada en URL no es siempre efectiva cuando se trata de manejadores “virtuales”, por lo que me quedaron 2 alternativas:

1. La más simple, implementar un manejador en un fichero físico, RunCmd.ashx. En este caso no es necesario registrar el manejador en el web.config, y desaparece el problema anterior, pues se trara de un fichero físico al cual se le aplican siempre las reglas de autorización, pues para acceder a él debe usarse siempre la misma ruta. Sin embargo, esta opción tiene como desventajas la reusabilidad en otras aplicaciones ASP.NET y la distribución, pues se trata de un fichero de código C# u otro lenguaje .NET seleccionado para implementar el manejador.

2. La otra opción sería implementar la lógica de autorización ad hoc en el propio manejador, pero tendríamos entonces el mismo problema anterior de reusabilidad, pues normalmente el mecanismo de seguridad varía de una aplicación a otra, lo cual implicaría reprogramar la lógica de autorización en cada aplicación que se fuese a usar el manejador.

En mi caso particular, resolvería con la primera opción, aunque en otros escenarios puede ser imprescindible que el manejador esté encapsulado en un esamblado, para aplicar sobre el mismo los mecanismos de integridad, autenticidad y seguridad que brinda .NET Framework, que no se pueden aplicar sobre ficheros de código, que en última instancia, son ficheros de texto.

Queda la puerta abierta, entonces, a aquellos entusiastas de ASP.NET que quieran implementar una alternativa flexible para definir y aplicar la seguridad sobre manejadores “virtuales”.

Tags: , ,

2 Responses to Autorizando manejadores “virtuales”

  1. paneque on marzo 27, 2009 at 3:17 am

    ya habia sufrido eso, si usas el type, corre como quiera que sea donde quiera que estes, eso en la actualidad es algo bueno, los controles de telerik por ejemplo usan muchos manejadores, ponerlos via un path seria un suicidio, tal como lo son actualmente los estilos css con caminos relativos etc.
    asi que por esa parte es bueno.
    lo del fichero realmente no es tan malo :) a la fine tu puedes definir en el web.config sub carpetas para codigo cualquiera, y tener sitios con vb y C# por ejemplo. de hecho tengo sitios en c# con manejadores en vb.net

  2. Román on marzo 30, 2009 at 9:31 am

    no sé si estaré respondiendo sin pensar, pero hacer que el http handler sea una capa fina sobre una clase que sería la reusable/distribuible/etc. quizás resuelva tu problema…

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

*

Acerca del autor...

Lester Sánchez

Web: http://www.linkedin.com/in/lestersanchez
Lester Sánchez
Profesor de la Facultad de Matemática y Computación de la Universidad de La Habana. Entusiasta de las tecnologías .NET y en especial de SharePoint. Webmaster de weboomania.comLeer completo