scieee AI-readable full text Open interactive document viewer

APIs de seguridad en .NET Framework

Domínguez Ruiz, Abel

Abstract

Este trabajo hace un estudio de algunas de las herramientas de seguridad disponibles en .Net Framework así como la forma de usarlas en un desarrollo web bajo la metodología de desarrollo de ASP.NET siguiendo el modelo Vista-Controlador y usando como entorno de desarrollo Visual Studio. Además de repasar las herramientas disponibles y la forma de uso se ha desarrollado también una aplicación de ejemplo: ItemCoteca-Web; en la que se demuestra cómo resolver el registro de usuarios, la autenticación y autorización de forma segura. En paralelo se ha implementado un cliente Android: Itemcoteca-app que realiza autenticación, registro y dispone de un chat seguro de incidencias para hablar con administradores OnlineEste trabajo no solo presenta las APIs disponibles sino también las buenas prácticas que define Microsoft para el uso de sus herramientas. En particular nos centramos en los tres tipos de controladores que podemos encontrar en una aplicación web Asp.net que son Controllers, WebApi y SignalR, comentando sus diferencias y su uso para clientes Web y móviles.

Full text

ESCUELA TÉCNICA SUPERIOR DE INGENIERÍA INFORMÁTICA Grado en Ingeniería del Software APIs de seguridad en .NET Framework Security APIs for .NET Framework Realizado por Abel Domínguez Ruiz Tutorizado por Isaac Agudo Ruiz Departamento Lenguajes Y Ciencias de la Computación UNIVERSIDAD DE MÁLAGA MÁLAGA, Noviembre de 2014 Fecha defensa: El Secretario del Tribunal Resumen Este trabajo hace un estudio de algunas de las herramientas de seguridad disponibles en .Net Framework así como la forma de usarlas en un desarrollo web bajo la metodología de desarrollo de ASP.NET siguiendo el modelo Vista-Controlador y usando como entorno de desarrollo Visual Studio. Además de repasar las herramientas disponibles y la forma de uso se ha desarrollado también una aplicación de ejemplo: ItemCoteca-Web; en la que se demuestra cómo resolver el registro de usuarios, la autenticación y autorización de forma segura. En paralelo se ha implementado un cliente Android: Itemcoteca-app que realiza autenticación, registro y dispone de un chat seguro de incidencias para hablar con administradores Online Este trabajo no solo presenta las APIs disponibles sino también las buenas prácticas que define Microsoft para el uso de sus herramientas. En particular nos centramos en los tres tipos de controladores que podemos encontrar en una aplicación web Asp.net que son Controllers, WebApi y SignalR, comentando sus diferencias y su uso para clientes Web y móviles. Palabras clave. Asp.net – Active Server Pages Visual Studio (VS) – Entorno de desarrollo creado por Microsoft Summary This document makes a study about the security tools in .Net Framework and how to use them in a web development under the ASP.NET development methodology Model-View-Controller and using Visual Studio as development environment. In addition to reviewing the available tools and how to use them, a sample application has also been developed: ItemCoteca-Web; in which it is shown how to solve user registration, authentication and authorization in a secure way. In parallel we have implemented an Android client: Itemcoteca-app that performs authentication, registration and has a secure online chat with managers ir order to resolve incedences. This work not only presents the APIs available, but also the good practices defined by Microsoft for their tools. In particular we focus on three types of controllers that can be found in a Asp.net web application: Controllers, WebAPI and SignalR, discussing their differences and their use for Web and mobile clients. Key words. Asp.net: Active Server Pages Visual Studio (VS) – Development Environment made by Microsoft Contenido Introducción ............................................................................................................................................. 1 Capítulo 1 Definición y estructuración correcta de un proyecto ASP.NET MVC ............................. 3 1.1 Convention over Configuration................................................................................................ 3 1.2 Tabla de rutas ......................................................................................................................... 4 1.3 Definiendo la estructura del proyecto ..................................................................................... 5 Capítulo 2 Data annotations y Validaciones Remotas ..................................................................... 8 2.1 Las data annotations, validaciones cliente ............................................................................. 8 2.2 Validaciones remotas ............................................................................................................ 11 2.3 IValidatatableObject .............................................................................................................. 13 2.4 EntityFramework para consultas a base de datos. ............................................................... 14 2.5 Defensa contra las inyecciones SQL .................................................................................... 16 Capítulo 3 Cifrado y Hash en C#. Paquete de clases Security. ..................................................... 18 3.1 Funciones Hash .................................................................................................................... 18 3.2 MD5 ....................................................................................................................................... 19 3.3 SHA1 ..................................................................................................................................... 20 3.4 GUID, Globally Unique Identifier ........................................................................................... 21 3.5 Cifrado simétrico ................................................................................................................... 22 3.6 Cifrado Asimétrico ................................................................................................................. 24 3.7 Generación de claves para cifrado y descifrado ................................................................... 25 3.8 Ejemplo de cifrado AES ........................................................................................................ 27 Capítulo 4 Control de Acceso en .NET ........................................................................................... 28 4.1 Explicación e introducción al contexto .................................................................................. 28 4.2 Autorización........................................................................................................................... 30 4.3 La interfaz IAttribute .............................................................................................................. 30 Capítulo 5 Descripción de la aplicación de DEMO, Caso de uso. ................................................. 33 5.1 Validación de Registro. ......................................................................................................... 33 5.2 Diagrama de secuencia generación token ............................................................................ 34 5.3 Diagrama de secuencia confirmación token ......................................................................... 35 5.4 Código de ejemplo de la generación del token ..................................................................... 35 Capítulo 6 Servicios REST Seguros en Android y C# .................................................................... 36 6.1 Web API ................................................................................................................................ 37 6.2 Consumo de un recurso Web Api en Android ....................................................................... 38 Capítulo 7 SignalR .......................................................................................................................... 40 7.1 Primeros pasos a SignalR ..................................................................................................... 41 7.2 Definición de nuestro Hub ..................................................................................................... 42 7.3 Configuración de la parte cliente web en Jquery .................................................................. 43 7.4 Los métodos Override de los Hub......................................................................................... 45 7.5 Mensajes privados por usuarios ........................................................................................... 46 7.6 Mensaje privado a grupos ..................................................................................................... 46 7.7 Como usar Android-SignalR-client ........................................................................................ 47 Conclusiones ......................................................................................................................................... 52 Anexo .................................................................................................................................................... 53 1 Introducción Para aclarar exactamente la motivación de este trabajo fin de grado, el lector ha de tener ciertos conocimientos sobre arquitecturas por capas, siguiendo el modelo Modelo-VistaControlador en el desarrollo de aplicaciones web, el haber desarrollado con anterioridad este tipo de aplicaciones web le será más fácil su comprensión. La evolución de ASP.NET MVC ha sufrido a lo largo de la historia de C# una corta, pero gran evolución debido al fracaso de SilverLight. Para entrar en contexto, SilverLight fue una tecnología basada en una arquitectura MV-VM, Modelo vista – Vista Modelo, que para ser usada era necesario la instalación de un Plugin en nuestro navegador. Pero al haber nacido los dispositivos móviles como los SmarthPhones y tablets, hizo que esta tecnología desapareciese debido a su incompatibilidad con estos dispositivos y Microsoft diese un paso al frente ofreciendo un producto nuevo y totalmente reorganizado, creando así el ASP.NET MVC que ahora se conoce y del que trata éste proyecto. El objetivo de este proyecto es que un usuario que nunca haya programado en ASP.NET MVC una aplicación empresarial, tenga una guía de referencia rápida o le sirva como aprendizaje autodidacta a la hora de desarrollar de forma correcta aquellos conceptos de seguridad básicos que debe de tenerse en cuenta en su desarrollo. Para ello vamos a explicar en primera instancia, las herramientas necesarias que hay actualmente en ASP.NET MVC para desarrollar la seguridad en una aplicación web sin entrar en gran detalle de: validaciones en servidor y cliente, evitar ataques de inyección SQL, las librerías criptográficas para cifrado y Hash, autorización, autenticación, uso de cookies, creación de recursos web, consumición de recursos a través de un cliente Android, ejemplos de cómo se deben de implementar todos y cada uno de los conceptos y además una introducción a SignalR, un framework dedicado a sistemas en tiempo reales en la web con un ejemplo entre el servidor ASP.NET MVC y un cliente Android. El contenido de la memoria se dividirá en dos partes, una de ellas será el cuerpo principal, donde explicaremos cada uno de los conceptos y herramientas de seguridad con ejemplos y la otra será un anexo donde explicaremos todo aquello que tenga relación con el contenido principal, pero que no sea relevante con el tema de seguridad o recursos web, como por ejemplo, configuración del entorno o explicación de algunos patrones. Todo lo que se explique a continuación no solo puede ser usado en una aplicación Web, si usted quiere desarrollar la lógica de negocio en web y esta ser usada además en un cliente remoto, puede utilizar WPF, o Windows Phone utilizando el mismo lenguaje, lo único que debería de cambiar es las interfaces gráficas de usuario. La estructura que sigue éste documento consistirá en una introducción a las herramientas de desarrollo, tras haber realizado ese paso hablaremos sobre como configurarlas y preparar nuestros proyectos. Tras estar listo para el trabajo duro, iremos desarrollando los casos de 2 uso que se encuentran en el anexo y explicando aquellas cosas que sean importantes para el propósito del trabajo fin de grado. Dado que es imposible en 50 páginas hablar de todo lo referido con C# en el anexo se podrá encontrar referencias a los patrones de diseños utilizados como información adicional, algunas de las buenas prácticas, y herramientas interesantes que trae C#. Para más información siempre se puede consultar la web de msdn en la que se puede encontrar casi todo lo referente a los frameworks y nuggets que usaremos. 3 Capítulo 1 Definición y estructuración correcta de un proyecto ASP.NET MVC Los primeros pasos que daremos en este proyecto será tratar de los aspectos más importantes de la convención entre los programadores C#. Todos los lenguajes tienen sus metodologías y sus formas correctas de definir sus componentes, clases, atributos, etc. C# también tiene su convención realizada por los desarrolladores, y a nivel mundial se ha declarado esta formalidad como el CoC Convention Over Configuration. Dado que no vamos a entrar en detalle cómo se debería de hacer correctamente cada una de ellas, explicaremos las más importantes para un proyecto en ASP.NET MVC 1.1 Convention over Configuration Convención sobre configuración es la metodología y filosofía que sigue un desarrollo mvc que busca reducir el número de decisiones que un desarrollador necesita tomar ganando así simplicidad pero sin perder flexibilidad. Esto significa que en la estructura de paquetes que tenemos nada más crear el proyecto debe de seguir esa convención y nunca salirnos de ella. Figura 1.1 En esta imagen vemos que tenemos una carpeta para los controladores (el nombre de sus clases debe de acabar en Controller) los modelos en la carpeta Models y las vistas en la carpeta Views, siguiendo así la estructura MVC. Cada vez que la aplicación necesite un controlador, hará la búsqueda en la carpeta raiz controlers, si la aplicación necesita acceder a un modelo de datos lo hará en la carpeta de datos, si nuestra aplicación necesita acceder a una vista lo hará en la carpeta de Views. Será en la tabla de rutas donde definamos que patrones de configuración necesitan las URL de la página para indicarle como hacer las búsquedas. 10 Figura 2.4 Con ModelState.IsValid sabremos si todos los campos del formulario han pasado las validaciones en el cliente. Realmente hacemos dos validaciones, una en el cliente y el ModelState valida lo mismo pero de parte del servidor, esto es así para asegurarnos de que si se accede al método de acción del controlador a través de un programa externo que no sea un navegador, le inyectemos los datos de forma incorrecta. Gracias al ModelState, se pueden evitar ataques del tipo SQL Injection, ya que internamente el framework generará expresiones irregulares para impedir la formación de cadenas que no concuerden con la definición del Data Annotation y además los valores son parametrizados. Hay decenas de Data annotations en asp.net mvc, pero se explicará a continuación las usadas en nuestro proyecto. 11 Figura 2.5 Required: El campo es requerido EmailAddress: Debe de cumplir un formato de dirección de correo electrónico Phone: Debe de ser numérico y además tener 9 dígitos MinLength: Tiene que ser al menos X caracteres MaxLength: Tiene que tener menos de Y caracteres Compare: Compara dos atributos del ViewModel, si son iguales devuelve true, en otro caso false. Range: El campo debe de comprenderse entre dos valores. Es útil para números de teléfonos o rangos de edad. Así es como se mostrarían finalmente las validaciones que no se han cumplido. Figura 2.6 2.2 Validaciones remotas En este apartado vamos a ver cómo funcionan las validaciones remotas en asp.net mvc, las validaciones remotas son unas validaciones cliente, es decir, que se ejecutan en cliente vía javascript pero que lo que hace es realizar una petición http post para hacer peticiones clientes que aceptan a datos del servidor. Por ejemplo, un caso muy simple que se puede resolver con validaciones remotas, es en nuestro formulario de registro queremos comprobar si un email de usuario está 12 registrado ya o no según vamos escribiendo el nombre o según cambiamos de textbox, realmente esta validación necesita comprobar datos de servidor porque el cliente no contiene esa información Tenemos varias maneras de realizar esto, una puede ser con Ajax, pasando como nombre de usuario cada vez que escribimos una letra al método del controlador para que haga la comprobación en la base de datos. Aunque podríamos hacerlo usando Ajax nativo, asp.net mvc nos lo trae integrado para poder hacerlo sin necesidad de usar Ajax. Para mostrar el ejemplo usaremos el anterior ViewModel de registro y utilizaremos el atributo email. Lo primero que debemos de hacer es utilizar el Data Annotation remote en nuestro atributo email de la siguiente manera Figura 2.7 Realmente el servidor no comprobará el validation remote hasta que la validación cliente esté correcta. Una vez se hayan cumplido las otras validaciones se hará la validación remota. Figura 2.8 Este sería nuestro método de la validación remota que se encargará de comprobar si el usuario ya existe o no en la base de datos, Si obtenemos null devolveremos una respuesta json que valdrá true, en otro caso devolverá false y ya el framework es lo suficientemente inteligente como para tratar la respuesta. De nuestra vista no debemos de cambiar absolutamente nada respecto al ejemplo anterior y esto será lo que obtengamos cuando el email ya exista en nuestra base de datos 13 Figura 2.9 2.3 IValidatatableObject Cuando queramos hacer validaciones complejas, que no solo acepte a un atributo, sino a varios de ellos o querramos hacer una validación implementando cierta lógica de negocio, con solo las Data Annotations explicadas anterior mente no nos bastaría. Para ello nace la interfaz IValidatatableObject, que al implementarla nos aparecerá como sobrescritura el método validate. Éste método no devuelve true o false por si ha funcionado bien, devolvemos una colección de ValidationResult que usará el framework para rellenar el ModelState. En éste ejemplo haremos un caso de uso en el que el usuario podrá cambiar su contraseña, para ello deberá introducir su email y su nueva password. Para realizar esta funcionalidad implementaremos la interfaz IValidatableObject en nuestro ViewModel correspondiente, en éste caso será el LoginViewModel. Figura 2.10 Si el método no devuelve nada, se trabaja como si no hubiese habido ningún error y el ModelState nos aceptará toda la validación como si fuese correcta y realizaríamos la lógica de negocio en nuestro controlador. 14 Figura 2.11 Éste sería el resultado de error tras comprobar nuestra validación y ver que es errónea 2.4 EntityFramework para consultas a base de datos. EntityFramework es la librería que nos permitirá trabajar con conexiones a base de datos y sus persistencias. La primera versión de EntityFramework apareció en 2008 y fue altamente criticada y anteriormente a EntityFramework, las consultas se realizaban nativamente en C# y se tenían que parametrizar las query nativamente de la misma manera que en Java., usando ADO.NET para updates, select, deletes e insert. La razón por la que nace EntityFramework es, una capa subyascente a nuestra lógica de negocio que se abstraiga del sistema gestor de base de datos que usemos. Si por ejemplo hacemos una consulta compleja en SQL y en un futuro debemos de cambiar la base de datos a Oracle, no tendríamos que cambiar todas las consultas en nuestro código. EntityFramework es una interfaz ORM que se comunica con la aplicación y por debajo con ADO.NET, que sería el encargado de realizar las llamadas a la base de datos. 15 Siguiendo la convención, las clases deben de llamarse en singular, las tablas en plural. A veces EntityFramework no es capaz de reconocer una clase y asociarla a su tabla correspondiente, haciendo que salten excepciones de código al ejecutarse. Para solucionar este problema se debe de usar el Data Annotation Table, el cual recibe como parámetro el nombre exacto de la tabla a la que hace referencia esa entidad. Figura 2.12 La clase que realmente utilizaremos para realizar las consultas y la comunicación extiende de DbContext, la cual sigue la siguiente estructura que hemos comentado siguiendo el CoC. 16 Figura 2.13 2.5 Defensa contra las inyecciones SQL A menudo, las aplicaciones obtienen entradas externas (de un usuario o de otro agente externo) y realizan acciones en función de dichas entradas. Cualquier entrada derivada directa o indirectamente del usuario o de un agente externo puede inyectar contenido que aproveche la sintaxis del lenguaje de destino para realizar acciones no autorizadas. Cuando el lenguaje de destino es del tipo de Lenguaje de consulta estructurado (SQL), como Transact-SQL, esta manipulación se conoce como ataque de inyección de SQL. Un usuario malintencionado puede inyectar comandos directamente en la consulta y quitar una tabla de la base de datos, provocar un ataque de denegación de servicio o cambiar de alguna otra forma la naturaleza de la operación que se está realizando. Los ataques de inyección de SQL se pueden realizar en Entity SQL proporcionando entradas malintencionadas a los valores que se utilizan en un predicado de consulta y en los nombres de los parámetros. Para evitar el riesgo de inyección de SQL, nunca debería combinar los datos proporcionados por el usuario con el texto de comandos de Entity SQL. Para ello usaremos las llamadas expresiones lambda a la hora de hacer nuestras consultas. Las expresiones lambda tienen implementadas realmente LINQ to Entities. LINQ to Entities proporciona la capacidad de realizar consultas integradas en lenguajes (LINQ) que permite a los desarrolladores de software escribir consultas contra el modelo conceptual de Entity Framework mediante Visual Basic o Visual 17 C#. Las consultas con Entity Framework se representan mediante consultas de árboles de comandos, que se ejecutan en el contexto del objeto. LINQ to Entities convierte las consultas de Language-Integrated Queries (LINQ) en consultas de árboles de comandos, ejecuta las consultas en Entity Framework y devuelve objetos que se pueden usar tanto en Entity Framework como en LINQ. A continuación se muestra el proceso para crear y ejecutar una consulta de LINQ to Entities. Una expresión lambda es una función anónima que se puede usar para crear tipos delegados o de árbol de expresión. Utilizando expresiones lambda, puede escribir funciones locales que se pueden pasar como argumentos o devolverse como valor de llamadas a funciones. Las expresiones lambda son especialmente útiles para escribir expresiones de consulta LINQ o EntityFramework. Pues bien, el framework ya está a adaptado para que intercepte todas aquellas cadenas de caracteres propias del lenguaje que sean SQL para interceptarlas y decidir si son válidas o no. Actualmente no se recomienda usar ADO.NET para realizar las consultas, porque con expresiones lambda o LINQ obtenemos dos cosas: 1) Seguridad anti inyecciones SQL o código malicioso 2) Rapidez a la hora de realizar consultas. Sería imposible hablar de todas las funcionalidades del EntityFramework y hay libros muy reconocidos para ello, pero como ejemplo, expondremos una consulta básica: Figura 2.14 Context sería nuestro contexto de datos, una instancia de la clase ItemcotecaDBEntities, que tendrá como propiedades los DbSet que se muestran en la figura 3.2. Usuarios sería la equivalencia a la tabla Usuarios, Where nuestra acción y aquí es donde entra en detalle las expresiones lambda. De esta forma parametrizamos totalmente los valores, ya que recordemos, que por debajo está ADO.NET que es el encargado de motorizar estas consultas. SingleOrDefault() devuelve el valor de la base de datos cuando realmente se sabe que solo existe uno o ninguno. Si por ejemplo existiesen dos correos exactamente iguales, SingleOrDefault devolvería un Exception, porque no sabría cuál de los dos devolver, para ese tipo de situaciones deberemos de usar el método ToList(); Para más información de EntityFramework, se puede consultar la bibliografía del anexo. 18 Capítulo 3 Cifrado y Hash en C#. Paquete de clases Security. En éste capítulo hablaremos de las primitivas criptográficas implementadas en .NET. Se explicará muy resumidamente una pequeña introducción a los tipos de cifrado y que posibilidades y herramientas ofrece .NET Framework En primera instancia hablaremos sobre las funciones hash que se usaran como checksum y para el almacén seguro de contraseñas y acto seguido sobre funciones de cifrado simétricas y asimétricas. 3.1 Funciones Hash Los hash que utiliza C# podemos obtenerlos desde el paquete de clases Sytem.Security.Cryptography. Antes de empezar con la implementación de las funciones hash haremos un pequeño recordatorio de que son. Las funciones hash asignan cadenas binarias de una longitud arbitraria a cadenas binarias pequeñas de una longitud fija. Una función hash criptográfica tiene la propiedad de que, mediante el cálculo, no es posible encontrar dos entradas distintas que generen aleatoriamente el mismo valor; es decir, los valores hash de dos conjuntos de datos deben coincidir si los datos correspondientes también coinciden. Pequeñas modificaciones en los datos ocasionan grandes cambios imprevisibles en el valor hash. Estas funciones son obligatorias para almacenar las contraseñas en nuestras bases de dato y está legalmente penado si no se cumple este requisito no funcional. Tanto MD5 como SHA1 pueden usarse para esta finalidad, pero en nuestro caso particular hemos decidido usar SHA1 para una mayor protección. Siguiendo lo establecido por la AGPD (Agencia Española de Protección de Datos) las contraseñas nunca deben de estar en texto claro y entendible por el ojo humano Toda la información respecto a estas funciones se puede consultar en el siguiente link a la Agencia Española de Protección de Datos. http://www.agpd.es/portalwebAGPD/canaldocumentacion/publicaciones/common/Gu ias/GUIA_SEGURIDAD_2010.pdf 19 3.2 MD5 El ejemplo de código siguiente calcula el valor hash MD5 de una cadena y devuelve el hash cómo una cadena hexadecimal de 32 caracteres. La cadena hash creada en éste ejemplo de código es compatible con cualquier función hash MD5 (en cualquier plataforma) que cree una cadena hash hexadecimal de 32 caracteres, el tamaño del valor hash del algoritmo MD5 es de 128 bits. Figura 3.1 Resultado obtenido desde la llamada de un web service: 26 4. Cada parte envía los datos a la otra parte y combina la clave secreta de la otra parte con la suya propia, en un orden particular, para crear una nueva clave secreta. 5. Después, las partes inician una conversación utilizando el cifrado simétrico. En ocasiones tendrá que generar varias claves. En este caso, puede crear una nueva instancia de una clase que implemente un algoritmo simétrico y después crear una nueva clave e IV mediante una llamada a los métodos GenerateKey y GenerateIV. En el ejemplo de código siguiente se ilustra cómo crear nuevas claves y vectores de inicialización una vez creada una nueva instancia de la clase criptográfica asimétrica. Ejemplo: TripleDESCryptoServiceProvider TDES = newTripleDESCryptoServiceProvider(); TDES.GenerateIV(); TDES.GenerateKey(); .NET Framework proporciona las clases RSACryptoServiceProvider DSACryptoServiceProvider y AESCryptoServiceProvider para el cifrado asimétrico. Estas clases crean un par de claves pública y privada cuando utiliza el constructor predeterminado para crear una nueva instancia.Las claves asimétricas pueden almacenarse para utilizarse en sesiones múltiples o bien generarse para una sesión únicamente.Aunque la clave pública puede ponerse a disposición general, la clave privada debe guardarse bien. Un par de claves pública y privada se genera siempre que se crea una nueva instancia de una clase de algoritmo asimétrico. Una vez creada una nueva instancia de la clase, la información de la clave puede extraerse mediante uno de estos dos métodos:  El método ToXMLString, que devuelve una representación XML de la información de la clave.  Método ExportParameters que devuelve una estructura RSAParameters que contiene la información de la clave. Ambos métodos aceptan un valor booleano que indica si hay que devolver sólo la información de la clave pública o si se devuelve también la correspondiente a la clave privada. El valor de una clase RSACryptoServiceProvider puede inicializarse con una estructura RSAParameters mediante el método ImportParameters. 27 Las claves privadas asimétricas nunca deben almacenarse literalmente o en texto sin formato en el equipo local. Si debe almacenar una clave privada, utilice un contenedor de claves. En el ejemplo de código siguiente se crea una nueva instancia de la clase RSACryptoServiceProvider, se crea un par de claves pública y privada, y se guarda la información de la clave pública en una estructura RSAParameters. //Generamos un par de llaves públicas y privadas. RSACryptoServiceProvider RSA = newRSACryptoServiceProvider(); //Guardamos la información de la llave pública en una estructura del tipo RSAParameters. RSAParametersRSAKeyInfo = RSA.ExportParameters(false); 3.8 Ejemplo de cifrado AES El cifrado AES viene de la interfaz AES, y la clase que lo implementa es AesCryptoServiceProvider. La forma de cifrar los bytes es necesario usar las clases CryptoStream y StreamWriter. CryptoStream definirá el modo de AES que son, modo cifrado modo descifrado como se muestra en el siguiente ejemplo: String plainText = “Cíframe”; ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); MemoryStream msEncrypt = new MemoryStream(); CrytpoStream CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)); StreamWriter swEncrypt = new StreamWriter(csEncrypt); swEncrypt.Write(plainText); La manera de descifrar cambia sutilmente, ya no podemos hacer directamente el cifrado desde un tipo string, necesitamos la array de bytes para hacer la operación inversa: String plainText = “”; ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); MemoryStream msDecrypt = new MemoryStream(cipherText) CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read) StreamReader srDecrypt = new StreamReader(csDecrypt) plaintext = srDecrypt.ReadToEnd(); 28 Capítulo 4 Control de Acceso en .NET Una vez explicado en el capítulo anterior la forma de cifrar el texto podemos introducirnos a la aplicación de todo lo anterior. En este capítulo hablaremos sobre cómo se realiza una autenticación de usuario cliente que venga desde un navegador web o un cliente Android. Éste capítulo está dedicado al Control de Acceso Basado en Roles (RBAC) es una función de seguridad para controlar el acceso de usuarios a tareas que normalmente están restringidas. Mediante la aplicación de atributos de seguridad a procesos y usuarios, RBAC puede dividir las capacidades de acceso a recursos entre varios tipos de roles. La gestión de derechos de procesos se implementa a través de data annotations. Para hacer una correcta autenticación es importante guardar la información mínima imprescindible en las cookies, que nos servirá para controlar los accesos de sesión y zonas restringidas en nuestra aplicación. La forma de realizar una autenticación y almacenar la información es con la clase HttpCookie. La clase HttpCookie tendrá para nosotros el mismo funcionamiento que un diccionario de datos, dado una key contendrá un determinado valor el cual podremos leer y escribir. Además podremos inyectarle el tiempo de expiración de la cookie en el servidor. Hay otra forma de realizar este funcionamiento con la clase FormsAuthentication pero no se puede trabajar con ella con la misma flexibilidad que HttpCookie, por lo que para aplicaciones que no requieran fuertes restricciones de datos FormsAuthentication nos arreglaría todos los problemas, pero para una aplicación con cierta lógica compleja se nos quedaría corta. 4.1 Explicación e introducción al contexto Imaginemos que un usuario inicia sesión en nuestra aplicación y necesitamos un cierto control para que estos usuarios no puedan acceder a determinados métodos o acciones de nuestro controlador o api, para poder implementar más tarde estas restricciones es importante almacenar la información de nuestro cliente, para ello vamos a realizar 3 acciones. La primera de ella será configurar el tiempo de inicio de sesión máximo de nuestras cookies de sesión, incluyendo además la redirección a nuestra URL de la vista login o que queramos para obligar al usuario que se autentique. Esto se hará en el fichero Web.config de nuestro proyecto y muy importante dentro del contenido de la etiqueta <system.web> 29 La segunda de ellas será redefinir el método Application_AuthenticateRequest en nuestro fichero Global.asax. Éste método de acción se ejecuta antes de cargar cualquiera solicitud a través de nuestro servidor web y lo utilizaremos para comprobar si hay actualmente una cookie de usuario asociado al usuario que inicia la petición y si es así almacenaremos la información en el servidor en una propiedad llamada user en nuestro contexto de la siguiente forma Context.user. La tercera de ellas será redefinir una clase que implemente interfaz IPrincipal. Ésta interfaz proporcionada por el framework está pensada para comprobar a posteriori los roles asociados a los usuarios y es obligatorio hacerlo para poder hacer muros de autorización. Context.user solo aceptará tener como parámetro una clase que implemente ésta interfaz. Ejemplo de autenticación Paso 1: Figura 4.1 Paso 2: Figura 4.2 Paso 3: Figura 4.3 30 Asp.net mvc implementa de una forma elegante la forma de controlar nuestras sesiones en el servidor, pudiendo separar la responsabilidad de cada acción en su clase y métodos correspondientes. Uno de los problemas que puede ocasionarnos quizás el guardar información de las cookies es que por ejemplo el nombre del usuario sea modificado y al realizar una petición engañemos al framework haciendo que haga la comprobación de autenticación con otro usuario, para solucionar esto hay varias maneras de hacerlo, desde usar JS, CA en las cookies etc. Pero realmente hay una forma muy sencilla de hacerlo que es asociar a un ID de sesión un Guid, es decir, en vez de guardar el correo del usuario en las cookies, generar un Guid en su sesión y asociársela en un campo de la tabla correspondiente a este usuario como un identificador más. 4.2 Autorización En este apartado vamos a comentar como se puede realizar una autorización de recursos en asp.net mvc. A diferencia de java, C# puede hacer comprobaciones de autorizaciones antes de entrar a los métodos de acción de un controlador, haciendo que sea imposible ejecutar la más mínima línea de código si no el usuario no está autorizado y además de una forma muy elegante, haciendo de forma fácil y estructurada la separación de responsabilidades Éste capítulo está dedicado al Control de Acceso Basado en Roles (RBAC) es una función de seguridad para controlar el acceso de usuarios a tareas que normalmente están restringidas. Mediante la aplicación de atributos de seguridad a procesos y usuarios, RBAC puede dividir las capacidades de acceso a recursos entre varios tipos de roles. La gestión de derechos de procesos se implementa a través de data annotations. 4.3 La interfaz IAttribute Las IAttributute son una serie de interfaces que nos dejan customizar e implementar el comportamiento del control a un determinado recurso, ya sea método, atributo de clase, etc. Estas interfaces se pueden usar para hacer restricciones como por ejemplo que la edad de una persona sea mayor de 18, que un campo no puede estar vacío, o contenga un determinado valor. Para las autorizaciones debemos de usar una en concreto llamada AuthorizeAttribute, ésta interfaz en concreto nos proporciona unos métodos de pre, post, in acción. Esto significa que tendrá un método que se ejecute antes de la llamada, otro durante la 31 llamada y otro después de la llamada. En mi caso particular he sobrescrito el método AuthorizeCore. El método AuthorizeCore recibe como parámetro un objeto de tipo HttpContext, este objeto guarda toda la información necesaria entre el usuario y el servidor. Podríamos acceder al debuger de nuestro VS y ver toda la información detallada, pero nosotros nos centraremos en la autorización. En el siguiente diagrama se muestra la secuencia que seguiría un usuario que intenta acceder a un sitio restringido sin haber logueado siquiera en nuestra aplicación. Client Server 1solicitudPaginaAutorizada 2.- comprobarCredenciales 3.- RedirecciónLogin 4.- Login(Correo,Password) 5.- ComprovaciónCredenciales 7.- ComprobarAutorizaciónByRol 8.- Redirección 6.- Actualizar Cookies Figura 4.4 En este código de ejemplo la acción que realizamos es relativamente sencilla, consiste en obtener por el constructor aquellos roles que van a poder acceder a un determinado recurso, estos roles serán comparados uno a uno por el método que sobrescribimos en el capítulo anterior en un objeto que implementa la interfaz IPrincipal. 32 Figura 4.5 La forma de poner estas restricciones se hace de la siguiente manera: Figura 4.6 Para finalizar es importante destacar que estas validaciones de autorización y autenticación se pueden usar también como etiquetas en nuestra Web Api y en signalR como veremos más adelante. 33 Capítulo 5 Descripción de la aplicación de DEMO, Caso de uso. Tras haber hecho una pequeña mención sobre en qué consiste una función Hash y ver varios tipos, vamos a mostrar su uso implementado en nuestro proyecto. La utilidad de estas funciones nos ha servido para autenticar el registro y proteger las contraseñas de los usuarios para que no sean entendibles al ojo humano. 5.1 Validación de Registro. Antes de comenzar con la explicación de la validación de registro hay que destacar que tabla y campos en la base de datos se han tenido que crear y explicar el porqué. Para el registro de usuario vamos a tener los siguientes campos para su validación: Atributo Descripción Posibles Valores Tipo Estado_Cuenta Es el estado de la cuenta de usuario el cual puede tener tres estados APOR – “Accont POR confirmar” ACON – “Account Confirmada” ABLO - “Account Bloqueada” String Token Es el token generado apartir del ID de la tabla usuario, el email con el que se registra el usuario y un número aleatorio generado por el servidor Hexadecimal obtenido de SHA1 String Random El número aleatorio con el que se ha generado el token Rango: 0 - 100.000 (int) Int La validación de registro es una manera de hacer que un usuario malicioso no pueda registrarse en un sitio web con la cuenta email de otra persona y haciéndose pasar por ella. Por ejemplo, si mi nombre es Abel y conozco el correo electrónico de Javier, podría registrarme con su email y bloquearle el acceso a la web con su correo. Para ello haremos uso de una comunicación de intercambio de tokens, a continuación explicaremos los pasos del protocolo: 34 1) El usuario envía el formulario con los campos correctos 2) El servidor comprueba que el email no existe en la base de datos 3) El servidor inserta los datos de usuario en la tabla Usuarios e inicializa el estado de la cuenta a “APOR” 4) El servidor obtiene el ID de usuario de la base de datos, genera un número random y concatena estos dos datos con el email que acaba de registrar el usuario SHA1(random+id+email) = Token 5) Generamos el SHA1 de esta concatenación y guardamos en la base de datos. 6) Creamos un email con formato de presentación 7) En el email creamos una URL con dirección al controlador que se encargará de completar el registro y además le pasamos como parámetro el token que generamos en el paso 4. 8) Cuando el usuario clickea en el link se vuelve a comunicar con el servidor 9) El servidor comprueba que efectivamente, ese token fue enviado y está a la espera de completar el registro 10) Cambia el estado de la cuenta de “APOR” a “ACON” 5.2 Diagrama de secuencia generación token Figura 5.1 35 En nuestra bandeja de entrada del correo electrónico aparecerá un mensaje con el siguiente formato. Figura 5.2 5.3 Diagrama de secuencia confirmación token Usuario RegistroContr oller RegistroRepo sitory 1 - CompletarRegistro(Token) 2 - ConfirmarRegistro(Token) ItemcotecaDB 3 - comprobarEcxistenciaToken 4 - respuestaExistente 5 - actualizarEstadoCuenta("ACON") 6 - OK 7 - cuentaValidada Figura 5.3 5.4 Código de ejemplo de la generación del token Figura 5.4 42 declarativas y sin esta clase de configuración jamás sería posible realizar esa comunicación entre cliente y servidor. Figura 7.1 Éste podría ser perfectamente un ejemplo de la configuración de nuestras clases Hub, lo que es realmente relevante es la etiqueta assembly que invoca al constructor de la clase OwinStartUp indicándole que esta clase debe de ejecutarse antes de cargar el contenido de nuestra web del servidor al cliente para configurar los hubs. El typeof indica la ruta donde está la clase, por defecto y recomendación es dejarla en ningúna carpeta o subdomino y que quede en la raíz del proyecto como el fichero Global.asax. 7.2 Definición de nuestro Hub El hub será la clase que contenga todos los métodos que se comunicarán entre el servidor y el cliente, actualmente signalR solo manda mensajes de texto, numéricos o booleans, es decir, no podemos mandar sonido o mandar imágenes. Para crear un Hub necesitamos crearnos una clase controlador que implementará la interfaz Hub, no es necesario crearla en una ruta específica pero la recomendación de los desarrolladores del framework es ponerla en una carpeta llamada Hub en la raíz del proyecto y ahí es donde desarrollaremos sus mensajes y su tratamiento como un controlador más. Figura 7.2 43 Éste ejemplo tiene declarado un Hub que tendrá como método un envió de mensaje global a todos los clientes que se subscriban a él. Realmente podríamos crear tantos hubs como quisiésemos para organizar nuestro proyecto, pero la recomendación es que solo tengamos uno donde englobemos todos los clientes para cerrar más de una conexión a nuestro servidor. Esto no quiere decir que siempre sea así, si por ejemplo nuestro proyecto se encarga de mandar mensajes a través de una aplicación llamada Tienda de Ropa, tendrá su propio hub, pero si tenemos además una funcionalidad de otra SubAplicación como Administradores de tienda, si es recomendable tener otro hub declarado impidiendo que nunca se conecten los dos hub a la vez desde una misma aplicación, ya que serían dos cosas totalmente distintas. Una vez declarado este hub también podemos configurarlo como los controladores anteriores y poner filtros de autorización Figura 7.3 Es importante recordar, sí que estas restricciones de autorización se colocan en el nombre de la clase, no se podrá acceder a ningún método pero si se podrá cargar la vista, para que no se cargue la vista debemos de poner el filtro de autorización en la cabecera de nuestro controlador, ya sea su clase o método, que haga acceso a la vista del chat que implementa el Hub. 7.3 Configuración de la parte cliente web en Jquery Para detallar el funcionamiento haremos una práctica sencilla de chat global, la gente puede conectarse al chat desde cualquier navegador compatible con asp.net mvc y que soporte las librerías jquery 1.6 o más. Con un diálogo le pedimos el Nick al usuario, en éste ejemplo nos conectaremos desde dos pestañas distintas del navegador. 44 Figura 7.4 Cada vez que escribimos los usuarios reciben el mensaje que cualquier persona escriba, no tenemos ningún control de quien entra o sale, de lo que se dice, o de enviar mensajes privados. Ya depende del desarrollador implementar toda la lógica que vea necesaria, ahora haremos un comentario de cómo funciona realmente las llamadas. Figura 7.5 Código de ejemplo Figura 7.6 45 Cómo podemos ver en el código cliente, cuando se realiza la sentencia chat.client.broadcastMessage, este broadcastMessage es una subscripción declarativa al método que tenemos en nuestra clase Hub en el servidor. Es importante tener cuidado de nombrarlas igual ya que no nos saldrá ningún error de compilación, de la misma manera que cuando creamos el proxy de conexión con la sentencia $.connection.chathub, chathub hace referencia a la clase controladora que implementa la interfaz Hub. 7.4 Los métodos Override de los Hub Hay tres métodos que se pueden sobrescribir en SignalR utilizados para la entrada, salida y reconexión de un cliente, estos métodos son respectivamente public override Task OnConnected(){ } public override Task OnDisconnected(bool stopCalled){} public override Task OnReconnected(){} Él método OnConnected es el primero en ejecutarse cuando un cliente comienza su conexión con el Hub. Éste método tiene muchas características importantes que puede implementar, si por ejemplo queremos usar un id único para cada usuario o comprobar u autenticación podemos hacerlo de la misma manera con la que autenticábamos en los controladores usando las cookies o usando la clase Context. Figura 7.7 Si por ejemplo queremos un identificador único para cada usuario, el propio framework nos da una ConnectionId que hace uso de los GUID para darnos un identificador único para cada usuario conectado al Hub. Él método OnDisconnected se ejecuta cuando el usuario ha cerrado el navegador o su sesión, y puede reescribirse también para limpiar las cookies, o mandar un mensaje a los demás usuarios advirtiéndoles de que usuario ha abandonado la sala de chat. 46 Él método OnReconnect se ejecuta cuando un usuario ha vuelto a conectarse sin haber pasado previamente por OnDisconnected. 7.5 Mensajes privados por usuarios Si quisiéramos enviar un mensaje privado a un usuario en concreto o un grupo de usuarios en concreto, SignalR tiene un método llamado Users propio de la clase Clients al que le podemos pasar una array, y todos aquellos usuarios cuyo Context.User.Identity.Name sea igual a uno de esos usuarios recibirá el mensaje: Figura 7.8 En este ejemplo recibimos por parámetro del mensaje, el Nick de la persona que lo envía, el mensaje y a los usuarios a los que se lo queremos enviar, además de 3 usuarios más. 7.6 Mensaje privado a grupos El mensaje privado por grupos es otra forma de enviar un mensaje a un cierto número por usuarios, solo que en esta ocasión los receptores del mensaje serán los usuarios subscritos a un grupo al que se le envía el mensaje. Si por ejemplo tenemos un canal de chat privado llamado “LCC” y enviamos el mensaje al grupo LCC, solo lo recibirán aquellas personas que pertenezcan a ese grupo. La forma de subscribirse a un grupo en concreto se hace de la siguiente forma: 47 Figura 7.9 Group.Add() recibe dos parámetros, el primero de ellos es una id por parte del usuario, podemos usar el Guid que nos proporciona el framework o podemos hacer uso del nick del usuario en el caso de que hayamos verificado que nunca se repetirá y lo mismo ocurre con el segundo parámetro que será el nombre del grupo o el identificador asociado a él. 7.7 Como usar Android-SignalR-client Para utilizar el cliente SignalR en Android debemos de utilizar una librería cliente que ya tiene implementada las conexiones para realizar las peticiones en el servidor. La forma de utilizar esta librería es muy similar a la usada para el cliente web y puede resultarnos bastante familiar. Para conectarnos al sevidor debemos primero configurar un objeto de tipo HubPoryx, y configurar la conexión: Figura 7.10 Una vez configurada los parámetros debemos de realizar la conexión a través de las siguientes sentencias. 48 Figura 7.11 7.7.1 Cómo realizar las llamadas: Figura 7.12 7.7.2 Cómo tratar las respuestas del servidor: Para tratar las repuestas del servidor debemos de declararnos las interfaces SubscriptionHandler, hay desde 1 hasta 5 elementos por respuesta, pero es raro que usemos más de 5, podemos customizarlas, el código es libre. Figura 7.13 Una vez declarado los handlers debemos implementar el funcionamiento de los handlers, o lo que es lo mismo, como vamos a tratar las respuestas del servidor: 49 Figura 7.14 Para finalizar nos queda solamente dar de alta nuestros handlers a las llamadas del servidor, el método on recibe 3 parámetros, 1) El nombre exacto de las respuestas del servidor 2) El handler que tratará esas llamadas 3) Los tipos de datos que vamos a recibir (el 3º parámetro es de tamaño N) Figura 7.15 A continuación mostraremos como es el protocolo de creación simple de un canal seguro con cifrado simétrico y algoritmo AES/CBC. 50 Cliente Maestro Venta Server 1.- SolicitarChatPrivado(id,asunto,comentario) 2.- NuevaSolicitudIncidencia(idSolicitante,asunto,comentario) 3.- RespuestaSolicitarChatPrivado(respuesta, estado) 4.- InicializarChatSeguro(idSolicitante) 5.- GenerarClaves 6.- Generamos grupo privado 7.- RecibirClaves(idChatSeguro,r,iv)7.- RecibirClaves(idChatSeguro,r,iv) 8.-AñadirMiembrosGrupoPrivado() 9.- MensajeChatSeguro(idChat,nombreEmisor,mensaje) 10.- GuardarMensaje(idchat,nombreEmisor,Mensaje) 11.- mensajeCifrado(emisor,mensaje) Figura 7.16 7.7.3 Cifrado de los mensajes en el chat seguro Para cifrar los mensajes al obtener las claves hemos de implementar los métodos de cifrar y descifrar. Es importante destacar que SignalR no acepta arrays de byte por lo que debemos de pasar el mensaje en formato de String y codificarlo en Base64. Si esto no lo hacemos así cuando recibamos el mensaje desde un cliente a otro no podremos descifrarlos y obtendremos un error de ejecución. 51 Figura 7.17 58 Diagrama de Tablas Usuarios ID int Nombre nchar(10) Apellidos nchar(10) Correo nchar(10) Telefono nchar(10) Movil nchar(10) ID_Rol int Fecha_Alta datetime2(7) Nombre de columna Tipo de datos Roles ID Nombre de columna Tarjetas ID NumeroTarjeta Nombre de colum... Pedidos ID int Fecha_Creación datetime Fecha_Estado_Final datetime Nombre de colum... Tipo de datos Estados_Pedidos int int Estado nchar(16) DescripcionEstad... nchar(10) Nombre de colum... Tipo de datos Permitir ... Seguimientos_Pedidos ID int ID_EstadoPedido int ID_Pedido int ID_Usuario int Nombre de colum... Tipo de datos Permitir ... Articulos ID int Foto nchar(10) Nombre nchar(10) Votos nchar(10) ID_TipoArticulos int Nombre de colum... Tipo de datos Permitir ... Lista_Articulos_Comprados ID int Nombre de colum... Tipo de datos Comprados ID_ListaArticulos int ID_Articulo int Nombre de colum... Tipo de datos Permitir ... Tiene ID_Pedido int ID_Articulo int Nombre de colum... Tipo de datos Factura ID int ID_Pedido int Nombre de colum... Tipo de datos Permitir ... Linea_Factura ID_Factura int ID_Articulo int Nombre de colum... Tipo de datos Log_Acceso Nombre de colum... Estados_Articulos ID int Estado nchar(10) Descripción nchar(10) Nombre de colum... Tipo de datos Logs_Estados_Articulos ID_EstadoArticulo int ID int ID_Articulo int ID_Usuario int FechaCambio datetime Nombre de colum... Tipo de datos Permitir ... 59 Instalación y configuración de los productos. Antes de adentrarnos en lo que serían los detalles técnicos de la aplicación y la seguridad en .net vamos a centrarnos en hacer un recorrido rápido de las herramientas que vamos a necesitar. Los productos que se han usado para éste proyecto han sido: - SQL Server 2012 R2 SP 2 - SQL Management Studio 2012 - Visual Studio 2013 SP 3 Todos ellos han sido prestados por licencias estudiantiles de la UMA en la página www.dreamspark.net. Una vez tengamos todos estos componentes estaremos preparados para poder continuar con la explicación. SQL Managment Studio. SQL Managment Studio es la herramienta gráfica que usaremos para definir nuestros diagramas de tablas. Aunque podamos hacer esto también de forma gráfica en Visual Studio es interesante explicar qué ventajas tiene este tipo de herramientas. Imaginemos que trabajamos en una gran corporación y necesitamos varios entornos para nuestro desarrollo software. Podríamos definir tres de ellos tales como Desarrollo, Preproducción y Producción. Con ésta herramienta podríamos conectarnos a las distintas bases de datos con unos perfiles de configuración. 60 Figura 1.1 Podemos Observar en la figura que hay una carpeta dedicada a “Seguridad”. Esta seguridad está integrada en nuestra base de datos y se abstrae totalmente de la seguridad que implementaremos más adelante en nuestra aplicación web. Figura 1.2 Éstos son los usuarios que nos crea por defecto y que para desarrollar en local realmente no necesitaremos cambiarlos, pero si en una gran corporación se necesita un control de quienes acceden a la información de determinados entornos requerirá una auditoría previa para definir bien los roles y privilegios de usuarios. 61 Creación de nuestra base de datos. Vamos a crear nuestra base de datos utilizando diagramas de tablas. Estos diagramás podremos sincronizarlos después con nuestro entorno visual studio de forma sincronizada, haciendo que cualquier cambio que hagamos tanto en SQL Management Studio como en Visual Studio afecten de la misma manera a nuestro contenido. Es importante destacar que trabajar directamente con SQL de forma local como localhost es bastante costoso, es decir, SQL es un gestor de base de datos muy potente pero que a su vez consume bastantes recursos. Si quisiéramos trabajar en un host de desarrollo que tenga hospedado nuestra base de datos y sitio web no tendríamos problemas en hacer un despliegue, pero para trabajar de forma local y con pocos datos hay otros métodos más eficaces. Para ello lo que usaremos será el localdb v11.0 LocalDB es una versión expres de SQL server, esto significa que no tiene el mismo rendimiento ni funcionalidad que esperaríamos del SQL Enterprise pero para trabajar en local es perfecto. La versión 2012 de SQL ya trae integrada esta versión express y no nos hará falta una instalación adicional como es en el caso de las otras versiones Enterprise que no lo traen ya de por sí. Para poder conectarnos a una localdb es tan sencillo como agregar una nueva conexión a servidor, Click en Archivo -> Conectar con Explorador de Objetos e introducir el nombre del servidor (localdb)\v11.0 Figura 1.3 Si todo ha ido correctamente nos deberá de aparecer la siguiente lista de bases de datos locales: master, model, msdb, tempdb. 62 Figura 1.4 Para crear nuestra base de datos solo debemos de hacer click derecho sobre el nuevo nodo que nos ha aparecido (Base de datos) crear nueva base de datos. En nuestro caso particular la hemos llamado ItemcotecaDB. Es importante elegir bien el nombre, ya que luego deberemos de usarla para sincronizarla con VS. Ahora podremos comenzar con nuestra creación de diagrama de tablas, seleccionamos la carpeta Diagrama de Base de datos que corresponde a la base de datos recién creada, al realizar esta acción nos aparecerá un Draw para poder dibujar el diagrama a nuestro gusto. Visual Studio Para sincronizar nuestra base de datos con VS debemos de irnos a la pestaña de explorador de servidores y agregar una nueva conexión. En la ventana de dialogo que nos aparecerá tendremos que introducir el nombre del servidor. Escribiremos el nombre del servidor (localdb)\v11.0 y en seleccionar el nombre de la base de datos debería de aparecernos la base de datos que acabamos de crear. 63 Figura 1.5 Llegados a éste punto, tenemos todo lo necesario para poder trabajar con datos almacenados, podemos hacer consultas de pruebas tanto desde un sitio como desde otro, incluso podemos crear nuestro diagrama de tablas desde el propio visual studio que explicaremos en los siguientes capítulos. Distinción de los proyectos base en ASP.MVC en Visual Studio En este apartado explicaremos cómo desarrollar con .Net una aplicación mvc en Visual Studio Lo primero que vamos a definir es el tipo y nombre de nuestro proyecto. Para ello elegiremos crear un nuevo proyecto en C# tipo web y nos aparecerán las siguientes opciones. Figura 1.1 64 La plantilla de Web Forms es una forma reducida de la potencia de mvc, sería algo así como el desarrollo clásico de webs, pero no para un proyecto profesional de gran escala. Trae su propio sistema de seguridad integrado básico, como autorización y autenticación, pero éstos métodos solo nos servirán para trabajar desde la plantilla. Asp.net MVC será el tipo de proyecto que nosotros debemos de elegir a la hora de trabajar para realizar proyectos empresariales. Figura 1.2 De aquí cabe destacar los siguientes: Aplicación de internet es una plantilla ya definida como web forms pero con estructura mvc 4, con su propio sistema de autorización y autenticación integrado. Web API Es el proyecto utilizado para definir servicios webs. Éste tipo de proyecto lo usaremos más adelante para definir nuestros servicios y comunicarnos con otros sistemas externos. Dado que éste proyecto busca utilizar las APIs de seguridad y la metodología de C# usaremos el tipo de proyecto Básico para nuestro entorno. Una vez creado el proyecto básico vamos hablar un poco respecto a la configuración para separarlo por capas y hacer que la implantación de la seguridad de la aplicación se pueda llevar acabo de forma correcta. 65 Patrones Inyección de dependencia (DI) y Repository. El patrón de inyección de dependencia y repository son dos patrones que van unidos de la mano, no se puede implementar el patrón de dependencia sin haber implementado anteriormente el Repository, y no tiene sentido implementar el patrón Repository si posteriormente no se implementa el Inyector de dependencia. El patrón repository consiste en crear una capa de abstracción entre nuestro modelo del dominio y los controladores que accederán a estas funcionalidades, abstrayéndonos así de la tecnología que haga uso de esta lógica de negocio. Un ejemplo sencillo de cómo se declararía la interfaz Un ejemplo de cómo se implementaría la interfaz Repository El patrón repository consiste en declarar interfaces o clases abstractas siguiendo el convenio I<NombreInterfaz>Repository, y la clase que implementará esta interfaz se llamará <NombreClase>Repository. Si por ejemplo yo quiero implementar una funcionalidad total referente a un registro de usuarios debería de crearme una 66 interfaz llamada IRegistroUsuariosRepository y la clase que la implementará se llamará RegistroUsuariosRepository. Inyección de dependencia El patrón DI, es un patrón aplicado a los controladores para abstraernos de la implementación de una interfaz y centrarnos simplemente en su funcionalidad. La forma de implementarla en un controlador es la siguiente: Cada vez que hagamos la llamada a un controlador éste se instanciará, y además, instanciaremos un repositorio con la implementación que nosotros queramos, así si en algún futuro debemos de hacer una modificación de la funcionalidad solo debemos de cambiar el código en un solo punto, ese punto es nuestra clase Bootstrapper 67 En el objeto container debemos de registrar el tipo de interfaz y la clase que lo implementa. Haciendo esto cada vez que queramos cambiar una funcionalidad aquí es donde debemos de cambiar las referencias, y no tener que ir buscando por todo el proyecto cuales controladores usaban nuestra interfaz y cuáles no.