ASP.NET MVC 3 y Structure Map

Como ya hemos hablado en otros post, una de las características que nos permiten mejorar el código de nuestros desarrollos es la utilización de patrones de diseño. Uno de esos patrones es la Inyección de Dependencias que consiste en suministrar objetos a una clase en lugar de ser la propia clase quien cree el objeto.

En este post voy a mostrarles un framework llamado Structure Map que nos permite aplicar este patrón en nuestros proyectos .NET y la forma de integrarlo al soporte de IoC que provee ASP.NET MVC 3.

Structure Map es un framework para .NET que nos permite trabajar con Inyección de Dependencias e Inversión de Control.

El primer paso sera agregar las referencias a la librería de Structure Map. Para ello vamos a instalarlas utilizando Nuget:

Agregando la librería Structure Map

Agregando la librería Structure Map

Es importante recordar que la pieza central respecto al soporte de IoC que provee ASP.NET MVC 3 es la interfaz IDependencyResolver que nos permite “conectar” distintos motores de IoC con tan solo implementarla en una clase y luego registrarla.

En nuestro ejemplo vamos a crear nuestro propio Dependecy Resolver que va a ser manejado con Structure Map. Para ellos vamos a crear la clase StructureMapDependencyResolver que, como dijimos anteriormente, implementará IDependencyResolver:

1: public class StructureMapDependencyResolver : IDependencyResolver
2: {
3:     private IContainer container;
4:
5:     public StructureMapDependencyResolver(IContainer container)
6:     {
7:         this.container = container;
8:     }
9:
10:     public object GetService(Type serviceType)
11:     {
12:         if (serviceType.IsAbstract || serviceType.IsInterface)
13:         {
14:             return this.container.TryGetInstance(serviceType);
15:         }
16:         else
17:         {
18:             return this.container.GetInstance(serviceType);
19:         }
20:     }
21:
22:     public IEnumerable<object> GetServices(Type serviceType)
23:     {
24:         return this.container.GetAllInstances<object>()
25:             .Where(s => s.GetType() == serviceType);
26:     }
27: }

Lo que hicimos aquí fue implementar los siguiente métodos:

En ambos métodos hemos utilizado el contedor IContainer (que nos provee la librería Structure Map) cuya finalidad es la de registrar y resolver las dependencias que hayamos definido.

Bien, ahora vamos a crear una interfaz bien simple, la cual denominaremos IMessage:
1: public interface IMessage
2: {
3:     string GetMessage();
4: }

Y dos implementaciones bien sencillas de la misma, la primera la llamaremos HelloMessage:

1: public class HelloMessage : IMessage
2: {
3:     public string GetMessage()
4:     {
5:         return "Buenos días!" ;
6:     }
7: }

Y la segunda ByeMessage:

1: public class ByeMessage : IMessage
2: {
3:     public string GetMessage()
4:     {
5:         return "Hasta mañana!" ;
6:     }
7: }

Llego el momento de registrar a nuestro “resolvedor(?) de dependencias”  🙂 y para ello debemos agregar las siguientes lineas en el archivo global.asax:

1: public class MvcApplication : System.Web.HttpApplication
2: {
3:     public static void RegisterGlobalFilters(GlobalFilterCollection filters)
4:     {
5:         filters.Add(new HandleErrorAttribute());
6:     }
7:
8:     public static void RegisterRoutes(RouteCollection routes)
9:     {
10:         routes.IgnoreRoute("{resource}.axd/{*pathInfo}" );
11:
12:         routes.MapRoute(
13:             "Default", // Route name
14:             "{controller}/{action}/{id}", // URL with parameters
15:             new { controller = "Home" , action = "Index" } 
16:         );
17:
18:     }
19:
20:     protected void Application_Start()
21:     {
22:         AreaRegistration .RegisterAllAreas();
23:
24:         RegisterGlobalFilters(GlobalFilters.Filters);
25:         RegisterRoutes(RouteTable.Routes);
26:
27:         InitializeContainer();
28:     }
29:
30:     public void InitializeContainer()
31:     {
32:         var c = InitContainer();
33:         DependencyResolver.SetResolver(new StructureMapDependencyResolver(c));
34:     }
35:
36:     private static IContainer InitContainer()
37:     {
38:         var container = new Container();
39:
40:         container.Configure(s => s.For<IMessage>().Use<HelloMessage>());
41:
42:         return container;
43:     }
44: }

Dentro del método Application_Start() invocamos un nuevo método llamado InitializeContainer() en el cual vamos a registrar StructureMapDependencyResolver como el encargado de resolver las dependencias. Previamente a este paso hemos creamos el método InitContainer() en el cual hemos creado un objeto Container al cual le fuimos configurando el mapeo entre interfaces y clases que sera utilizado para poder resolver las dependencias (en el ejemplo solo es uno y es el de IMessage).

Es hora de crear el controlador HomeController cuyo constructor recibirá como parámetro un IMessage el cual será “inyectado” cada vez que sea instanciado (de lo cual ya no debemos preocuparnos gracias a IDependencyResolver). También vamos a definir un método de acción Index:

1: public class HomeController : Controller
2: {
3:     private IMessage MessageService { get ; set ; }
4:
5:     public HomeController(IMessage service)
6:     {
7:         this .MessageService = service;
8:     }
9:
10:     public ActionResult Index()
11:     {
12:         ViewBag.Message = MessageService.GetMessage();
13:
14:         return View();
15:     }
16: }

Ejecutamos y veremos que el servicio instancia es el que hemos definido al momento de crear el contenedor, en este caso HelloMessage:

Resultado obtenido de HelloMessage

Resultado obtenido de HelloMessage

Ahora modificamos el contenedor para instanciar el servicio ByeMessage en la interfaces IMessage:

1: private static IContainer InitContainer()
2: {
3:     var container = new Container();
4:
5:     container.Configure(s => s.For<IMessage>().Use<ByeMessage>());
6:
7:     return container;
8: }

Ejecutamos y verificamos que se invoco el servicio que definimos:

Resultado obtenido con ByeMessage

Resultado obtenido con ByeMessage

De más esta decir, que esto simplifica y mejora el código de nuestros desarrollos, ya que en el caso de que debamos modificar la referencias a nuestros servicios, y si estos mantienen el contrato, solo debemos modificar una sola línea de nuestro proyecto, y es el mapeo entre interfaz y clase que hemos configurado en el contenedor de dependencias.

Quienes quieran descargar el proyecto pueden hacerlo desde acá: MvcAndStructureMap.rar.

Espero que les sea de utilidad.

Disponible ASP.NET MVC 4 Roadmap

ASP.NET MVC

ASP.NET MVC

En el día de hoy me he encontrado con una gran noticia, y es que están por comenzar a trabajar en una nueva versión de ASP.NET MVC.

Ya podemos acceder al documento con la planificación del trabajo de ASP.NET MVC 4, el cual no es definitivo, pero nos da pautas de las nuevas características que va a ofrecer esta versión.

Uno de los objetivos es generar una de las mejores plataformas de desarrollo de aplicaciones web modernas (rich web apps) y multi-plataforma (ya veremos que varias de las características estan relacionadas a los dispositivos mobiles o tablets, como también a HTML 5).

Algunas de las características que ofrecería son:

  • Recipes (Extensible Task-Based Tooling): en ASP.NET MVC 4 un Recipe es básicamente una caja de dialogo entregada vía Nuget para implementar ciertas carateristicas automaticamente, como por ejemplo: Ajax grid, autentificación mediante OAuth o claims utilizando Windows Identity Framework (WIF) entre otros. La idea es que uno también pueda escribir sus propios Recipe y reutilizarlos en otras aplicaciones.
  • Mobile Support: en los nuevos proyectos web tendremos plantillas CSS optimizadas para la visualización de nuestro sitio en dispositivos móbiles y tablets. También podremos crear “Mobile Applications” las cuales trabajaran con jQueryMobile para aplicaciones que estan orientadas a dispositivos mobiles unicamente.
  • Razor Helpers Support: la idea es continuar utilizando el viewengine Razor y mejorar la forma de escribir Helpers para las web pages.

Pueden ver en detalle estas característicamente y muchas otras más desde aquí.

Evitando JavaScript Injection en ASP.NET MVC

Hace unos días revisando un informe de sobre seguridad web, un ítem me llamo la atención porque es una de esas cosas que a uno se olvida de tenerlas en cuenta al momento de desarrollar un sitio. El mismo hablaba sobre los ataques de inyección de JavaScript.

Este tipo de ataque se denomina Cross-site scripting o de manera abreviada XSS:

XSS, del inglés Cross-site scripting es un tipo de inseguridad informática o agujero de seguridad basado en la explotación de vulnerabilidades del sistema de validación de HTML incrustado.

La idea de este post es ver de que forma podemos prevenir este tipo de ataques en aplicaciones ASP.NET MVC partiendo desde dos ópticas diferentes.

Antes que nada vamos a ver un poco mas en profundidad de que se trata JavaScript Injection y como se llevan a cabo este tipo de ataques. Para darnos una mejor idea supongamos que desde nuestro sitio web tenemos una caja de texto en la cual un usuario carga contenido y luego el mismo se visualiza en la página. Esta situación podría estar dejando abierta la posibilidad de un ataque de inyección de Javascript. Cómo es posible esto?… vamos a verlo con un simple ejemplo.

Lo primero sera crear una aplicación web tipo Twitter pero muy simplificada, en la cual vamos a permitir este tipo de ataques. Vamos a crear un controlador al cual vamos a llamar TweetController y a definir la siguiente entidad que formará parte del modelo de nuestra app y que se llamaremos Tweet:

1: public class Tweet
2: {
3:     public int TweetID { get ; set ; }
4:
5:    public string Usuario { get ; set ; }
6:
7:     public string Mensaje { get ; set ; }
8: }

Al momento de codificar la vista, la visualización de los items estará armada de la forma estandar:

1: <div class="tweetSection">
2:  <% foreach (var item in Model) {  %> 
3:     <span class="tweetUser">  <%= item.Usuario %></span>
4:    <br />
5:      <%= item.Mensaje  %> 
6:     <br />
7:     <br />
8:  <%   }  %>
9: </div>

Básicamente nuestra app esta conformada por un formulario donde se ingresa un nombre de usuario y un mensaje, el cual al momento de hacer el submit se grabara en una DB (para esto utilizaremos la librería EF) y luego se visualizara en la misma pantalla:

Interfaz de la aplicación

Interfaz de la aplicación

De la forma en que “dibujamos” el formulario, hemos dejado desprotegido nuestro sitio a los ataques de este tipo. Imaginemos que el usuario escribe un simple script de Javascript en nuestra caja de texto, por ejemplo, la ejecución de un mensaje de alerta informándonos que hemos sido atacados:

Cargando un script JS en el formulario

Cargando un script JS en el formulario

Una vez que “tweeteamos” nuestro contenido y volvemos a cargar la vista (que incluye la visualización del contenido de cada uno de los tweets) se estará ejecutando nuestro script:

Ataque de Javascript Injection

Ataque de Javascript Injection

Uno puede pensar que este tipo de ataques son inofensivos, sin embargo un hacker podría utilizar la inyección de JavaScript para realizar un ataque Cross-Site Scripting (XSS) robando información confidencial del usuario y enviando la misma a otro sitio web (dos ejemplos clásicos serían robar información de las cookies del navegador del usuario o información que se carga en un formulario que previamente a sido victima de Javascript Injection).

Cómo podemos evitar este ataque? Tenemos dos alternativas, la primera es utilizar el helper HTML.Encode el cual se encargara de renderizar el contenido de forma tal que no se ejecuten scripts que alguien pudo ingresar:

1: <div class="tweetSection">
2:  <% foreach (var item in Model) {  %> 
3:     <span class="tweetUser">  <%= item.Usuario %></span>
4:     <br />
5:      <%= Html.Encode(item.Mensaje)  %> 
6:     <br />
7:     <br />
8:  <%   }  %>

Ejecutamos y vemos que ya no se ejecuta nuestro script, ya que todo contenido reconocido como HTML a sido codificado de forma tal que se pueda visualizar como texto:

Utilizando el Helper Html.Encode

Utilizando el Helper Html.Encode

La segunda alternativa es codificar el contenido antes de grabarlo en la base de datos. Para esto podemos hacer uso del método Server.HtmlEncode que nos provee nuestro controlador:

1:             if (ModelState.IsValid)
2:             {
3:                 tweet.Mensaje = Server.HtmlEncode(tweet.Mensaje);
4:                 datos.Tweets.Add(tweet);
5:                 datos.SaveChanges();
6:             }

Utilizando este esquema ya no sería necesario utilizar el helper Html.Encode para visualizar el contenido (aunque no esta demás dejarlo). La desventaja de este enfoque es que los datos que se graban en la base de datos están codificados, lo cual no es del todo prolijo sobre todo si esta información se necesita visualizar en otro tipo de plataformas que no sean web. Observemos a continuación como se guardan los datos sin codificar (registro 2) y codificandolos (registro 3):

Registros de la base de datos

Registros de la base de datos

Para finalizar quería comentarles que utilizando el ViewEngine Razor los datos son “encodeados” automaticamente, sin necesidad de utilizar el helper Html.Encode y previniendonos de este tipo de ataques de entrada.  🙂

Quienes quieren el proyecto del ejemplo pueden descargarlo desde aquí: Projecto MvcJavascriptInjection