Seguridad Personalizada

La capa de seguridad de MVC es una capa independientemente de las demás capas de un Proyecto de un MVC

Podemos añadir o quitar el capa de seguridad en cualquier momento de la creación del proyecto sin afectar a la funcionalidad del proyecto.

Lo que sirve la capa de seguridad es limitar el permiso de acceso a cierta página del proyecto por diferente role.

SOLUCIÓN RÁPIDA (copia código y Ya está)

Preparación

la capa de seguridad se implementa sobre un proyecto de MVC funcional.

Así que, para la mostración de la implementación de la capa de seguridad, creamos un proyecto de ASP.NET con plantilla de MVC.

1º_post_01
Que contiene dos Controlador: Empleado y Home .
1º_post_02
En el controlador de empleado contiene un método de GETLISTAEMPLEADO para obtener el listo del empleado (como este proyecto lo utilizamos para la demostración de capa de seguridad, utilizamos este método como un repositorio de un BBDD para facilitar la fase de creación del proyecto).
1º_post_03
Tambien tenemos un ACTION que devuelve una Vista llamado LISTAEMPLEADO que muestra el listado de los empledos.
1º_post_04
1º_post_05
El controlador de Home Solo contiene un ACTION del Vista Index que muestra un LINK que dirige al Vista del LISTAEMPLEADO del controlador EMPLEADO.
1º_post_06
1º_post_07
1º_post_08

Si hacemos click sobre ese link nos lleva directamente al vista de la lista de empleado sin ningun problema.

1º_post_09

Ejemplo de implementar la capa de seguridad

Lo que vamos a hacer es limitar el permiso de acceso al Vista de LISTADOEMPLEADO, solo el usuario que esta iniciado sesion y tiene el permiso de ADMIN puede entrar

Paso que necesitamos hacer

  • 1º paso crear controlador manage
  • 2º paso configurar el fichero global.asax
  • 3º paso crear AutorizarAttribute
  • 4º paso implementar el AutorizarAttribute en el controlador o vista que quiere limitar el permiso de acceso
  • 5º paso crea vista parcial para cerrar sesión

1º PASO crear controlador Manage

Creamos un controlador de manage(el nombre de controlar puede ser persalizado) lo utilizamos para manejar el login del usuario.

1º_post_10
En el controlar creamos 4 ACTION que vamos a necesitar:
  • GET: LOGIN (mostrar la vista de login para iniciar sesion)
  • POST:LOGIN(realizar autenticacion de cuenta y redirecionar al pagina del lista empleado)
  • GET: ERRORACCESO(que se devuelve una vista que muestra el mensaje de que no tienes permiso de acceso de la pagina)
  • GET: CERRARSESION(es una ACTION que utiliza para cerrar cession del usuario)

GET:Login (mostrar la vista de login para iniciar sesion) .

1º_post_11
1º_post_12

En la vista del login contiene un formulario para enviar los datos del usuario y password de formato POST.

1º_post_13

POST:Login(realizar autenticacion de cuenta y redireccionar al pagina del lista empleado).

En el posta del Login recibimos el nombre de usuario y password Primero realizamos la comprobacion de que si existe el usuario o no .

Para facilizar el proceso de comprobacion aquí utilizamos un “IF” y solo con la cuenta del admin y del empleado, pero lo mas completo de realizar una comprobacion es conectar el proyecto con un BBDD y hacer la comprobacion con la tabla User.

Si el usuario y password que hemos recibido conincite con el admin o empleado añadimos el role y idempleado que pertenece a variable “role” y “idempleado” .

1º_post_14

Después de la comprobación, si existe el usuario crea un TICK para almacenar los datos necesarios para crear una cookie.

Un TICK necesita siguientes datos.

  1. Numero de versión (de ejemplo ponemos 1)
  2. Nombre de identidad
  3. Fecha y hora de inicio
  4. Fecha y hora de expirar (indicar cuanto tiempo va a durar este TICK, puede ser minutos, horas o días)
  5. Persistente
  6. Un dato de tipo STRING que deseamos guardar para que podemos recuperar luego (en nuestro ejemplo guardamos el “role” del usuario)
1º_post_15

Despues lo ciframos el TICK y lo guardamos en un COOKIE llamado “Usuario”.

Y despues hacemos un redireccion a la pagina de ListaEmpado del controlador Empleado.

El cookie que hemos creado lo utilizamos luego en la Golbal.asax para crear la sesion.

1º_post_16
En caso de no ha pasado la comprobacion lo enviamos de vuelta a la pagina de LOGIN para que vuelva ha introducir el Usuario y la contraseña.

GET: ErrorAcceso(devulve una Vista que se muestra el mensaje de que no tienes permiso de acceso de la pagina).

1º_post_17
1º_post_18

GET: CerrarSesion(se utiliza para cerrar cesion del usuario y redirecciona al pagina index del Home).

1º_post_19

2º PASO Configurar Global.asax

Lo que hacemos en goblal.asax es meter el cookie del “Usuario” que hemos creado en el HTTPCONTEXT.CURRENT.USER.
1º_post_20
Dentro de Globax.Asax creamos un método con nombre de APPLICATION_POSTAUTHENTICATEREQUEST (ES METODO QUE SE EJECUTA EN EL SERVIDOR CON CADA INTENTO DE VALIDACION DE USUARIO).

Vamos a necesitar utilizar la siguiente libreria.

1º_post_21
lo que hacemos primero es una comprobación si existe el COOKIE del “Usuario” o no . sí existe, desciframos el COOKIE y usamos los datos de la cookie para crear un objeto GENERICPRINCIPAL y lo guardamos en el HTTPCONTEXT.CURRENT.USER.
1º_post_22

3º PASO crear AutorizarATTRIBUTE

Es una clase que esta heredada del AUTHORIZEATTRIBUTE .
1º_post_23

El nombre de” Autorizar” es personalizable, pero es obligatorio que termina con “Attribute”.

Esta clase lo utilizamos para comprobar si el usuario esta autentificado o no y también podemos limitar el permiso de acceso de cierta pagina.

Por ejemplo, ahora vamos a limitar que, solo el usuario que tiene role de ADMIN puede entrar en la página de LISTAEMPLEADO.

Librería que necesitamos.

1º_post_24
La clase debe estar heredado del AuthorizeAttribute.
1º_post_25
Creamos una sustitución del método OnAuthorization para realizar el autenticado del usuario.
1º_post_26
Con el primer “if” comprobamos si el usuario esta autenticado o no. Si está autenticado capturamos su role desde HttpContext.Current.User Si tiene el role de ADMIN lo dejamos entrar en la página de la LISTAEMPLEADO si no lo enviamos a la página de ERRORACCESO.
1º_post_27
Si no está autenticado le redireccionamos a la vista de LOGIN para que realiza la autenticación.
1º_post_28

4º paso implemetar el el Attribute Autorizar en el controlador o vista que quiere limitar el permiso de acceso

primero hacemos el using del carperta Attribute.

1º_post_29

Para implementar la autenticación solo tenemos que añadir el [Autorizar] por encima del ACTION o CONTROLADOR que deseamos implementar la autenticación.

[Autorizar](es el nombre de clase de autenticación que hemos creamos) por defecto se omite el Attribute.
1º_post_30
Por ejemplo, lo añadimos al ACTION del LISTAEMPLEADO () del controlador EMPLADO.
1º_post_31

5º paso crea vista parcial de cerrar sesion

Tenemos que crear una Vista Parcial en el menú de navegación para que podemos cerrar sesión después iniciar sesión.

El menú de navegación suele estar en el LAYAOUT así que para crear la vista parcial en la carpeta SHARED para que podamos llamar desde LAYOAUT.
1º_post_32
1º_post_33

Usamos un “if” para que solo se muestre esta vista parcial cuanto el usuario esta autenticado.

Y contiene una LINK que llama el método que hemos creado ante en el controlador de manager que sirve para cerrar sesión.

1º_post_34
En LAYOUT utilizamos el HTML.PARCIAL para añadir la vista parcial de cerrar sesión.
1º_post_35

COMPROBACION

Ejecutamos el Proyecto, hacemos clic sobre el LINK del LISTAEMPLEDO
1º_post_36
Y no entrar directamente como antes, si no, nos redirecciona a la página de LOGIN Primero probamos iniciar sesión con la cuenta de ADMIN
1º_post_37

Después de iniciar sesión nos a dejado entrar en la página de lista empleado y también nos muestra la opción de cerrar sesión.

1º_post_38

Ahora cerramos sesión y iniciamos de nuevo con la cuenta de Empleado.

1º_post_39

Podemos ver que no tenemos permiso de acceder a la página del listado empleado .

1º_post_40

Posible Problema

Con la configuración que hemos hecho anteriormente, hay un problema sobre el POST de LOGIN.
1º_post_41
Después de iniciar sesión siempre va a redireccionar a la página de LISTAEMPLADO.
1º_post_42
Por ejemplo, si creamos un nuevo ACTION llamado DETALLEEMPLEADO en el controlador EMPLEADO y añadimos la Autenticación.
1º_post_43
Añadimos un nuevo link en la página INDEX de HOME.
1º_post_44

Cuando hacemos clic sobre link de “Perfil” nos pide que iniciemos la sesión.

1º_post_45
Pero después de iniciar sesión siempre nos lleva a la página de LISTAEMPLEADO y no a la página de detalles que hemos querido.
1º_post_46
Eso es por lo que he mencionado antes en la ACTION de POST de LOGIN tenemos un REDIRECTTOACTION con una dirección estática por eso siempre nos va a llevar siempre a la página de LISTAEMPELADO después de iniciar sesión.
1º_post_47
Tenemos que cambiar el REDICTTOACTION de la dirección estática a dinámica Para solucionar este problema tenemos que modificar la clase AUTORIZARATTRIBUTE y el ACTION POST de LOGIN

En la clase de AUTORIZARATTRIBUTE

Primero capturamos el ACTION y CONTROLADOR que el usuario desea ir (capturar el usuario en que LINK ha hecho click) utilizando el ROUTEDATA.VALUE.
1º_post_48
1º_post_49
Como cuando hacemos click sobre el LINK, es la primera vez que entramos en la AUTORIZARATTRIBUTE no va a estar autenticado así que guardamos el ACTION y el CONTROLADOR que hemos capturado en TEMPDATA para poder recuperarlo luego en POST de LOGIN.
1º_post_50

En el POST DE LOGIN (controlador de MANAGE)

En el POST de LOGIN recupera el ACTION y CONTROLADOR que hemos guardado y redireccionamos dinámicamente a la página que el usuario deseado ir (en la siguiente imagen hay un “if” porque el ACTION de DETALLAEMPLADO necesita recibir un IDEMPLEADO)
1º_post_51

Comprobación:

1º_post_52
1º_post_53
1º_post_54

Solución Rápido (Sin preguntar porque COPIA y PEGALO siguiente código a tu PROYECTO DE MVC):

Volver

Crear un Controlador llamado Manage

1º_post_55

Las librerías que necesita para el ManageController

using System.Web.Mvc;
using System.Web.Security;

Y copia siguiente código y pégalo dentro del ManageController

public ActionResult Login()
        {
            return View();
        }

        [HttpPost]
        public ActionResult Login(string usuario, string password)
        {
            string role = null;
            int idempelado=0;
//esta parte puede cambiarlo por un metodo que comprueba si el usuario y password que recipido coincide con tu BBDD o no
       
            if (usuario.ToUpper() =="ADMIN" && password.ToUpper()=="ADMIN")
            {
                role = "ADMIN";
                idempelado = 4;
            }
            else if (usuario.ToUpper() == "EMPLEADO" && password.ToUpper() == "EMPLEADO")
            {
                role = "EMPLEADO";
                idempelado = 1;
            }          
            
            if (role != null)
            {  
                                       
                FormsAuthenticationTicket ticket = 
                    new FormsAuthenticationTicket
                    (
                        1,
                        idempelado.ToString(),//este el valor que vamos a guarda en HttpContext.Current.User.Identity.Name
                        DateTime.Now, 
                        DateTime.Now.AddMinutes(10),
                        true,
                        role //este es variable que guarda el valor de role 
                    );
                              
                string datos = FormsAuthentication.Encrypt(ticket);
            
                HttpCookie cookie = new HttpCookie("Usuario", datos);
             
                Response.Cookies.Add(cookie);

                string action = TempData["action"].ToString();
                string controlador = TempData["controlador"].ToString();

                if (action== "DetalleEmpelado")
                {
                    return RedirectToAction(action, controlador, new { idEmp = idempelado });
                }
                else
                {
                    return RedirectToAction(action, controlador);
                }
                
            }
            else
            {              
                ViewBag.mensaje = "Usuario/Password incorrecto";
                return View();
            }

        }


        public ActionResult ErrorAcceso()
        {
            return View();
        }

        public ActionResult CerrarSesion()
        {         
            HttpContext.User = null; 
            FormsAuthentication.SignOut();
            HttpCookie cookie = Request.Cookies["Usuario"];
            cookie.Expires = DateTime.Now.AddMinutes(-30);
            Response.Cookies.Add(cookie);
            return RedirectToAction("Index", "Home");
        }

Crear Vista de LOGIN y ERRORACCESO

1º_post_56

VISTA LOGIN:

Copia siguiente código y sustituir todos los contenitos de la Vista de LOGIN

@{
    ViewBag.Title = "Login";
}

<h2>Login de Usuario</h2>

@using (Html.BeginForm())
{
    <div>
        <label>Usuario :</label>
        <input type="text" class="form-control" name="usuario" placeholder="Nombre de Usuario" />
    </div>

    <div>
        <label>Password :</label>
        <input type="password" class="form-control" name="password" placeholder="Clave de acceso" />
    </div>
    <br />
    <div>
        <button type="submit" class="btn btn-success">Login</button>
    </div>

}

<h1 style="color:red">@ViewBag.Mensaje</h1>

VISTA ERRORACCESO:

Copia siguiente código y sustituir todos los contenitos de la Vista de ERRORACCESO


@{
    ViewBag.Title = "ErrorAcceso";
}

<h2>ErrorAcceso</h2>

Crear Vista Parcial de CERRARSECION en SHARED

1º_post_57
1º_post_58

Copia siguiente código en tu Vista de CERRARSECION

@if (HttpContext.Current.User.Identity.IsAuthenticated)
{   
    <li>@Html.ActionLink("Cerrar sesion","CerrarSesion","Manage")</li>
}

En tu LAYAOUT añadir siguiente código en tu menú de navegación para mostrar la opción de cerrar sesión

@Html.Partial("_CerrarSesion")

Crear una carpeta Attribute y crear una clase con nombre de AutorizarAttribute

1º_post_59

Elimina todos lo que tiene dentro del AutorizarAttribute copia siguiente código y pegarlo en AutorizarAttribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace post_Segurida_MVC.Attribute
{
    public class AutorizarAttribute: AuthorizeAttribute
    {
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            base.OnAuthorization(filterContext);
        
            string controladorOrigen = filterContext.RouteData.Values["controller"].ToString();
            string actionOrigen = filterContext.RouteData.Values["action"].ToString();
          
            if (filterContext.HttpContext.Request.IsAuthenticated)
            {
                GenericPrincipal user = (GenericPrincipal)HttpContext.Current.User;
               
             // aqui se puede un if para que limitar el acceso por role
             //if (user.IsInRole("ADMIN") == false)
                    //{
                    //    //nos lo llevamos a sin acceso
                    //    RouteValueDictionary ruta = new RouteValueDictionary(new { Controller = "Manage", action = "ErrorAcceso" });
                    //    filterContext.Result = new RedirectToRouteResult(ruta);
                    //}
            }
            else
            {  
filterContext.Controller.TempData["action"] = actionOrigen;                          
                filterContext.Controller.TempData["controlador"] = controladorOrigen;             
                RouteValueDictionary rutalogin = new RouteValueDictionary(new { controller = "Manage", action = "Login" });             
                filterContext.Result = new RedirectToRouteResult(rutalogin);
            }
        }
    }
}

Configurar Fichero GLOBAL.ASAX

copia siguiente código en tu Fichero de GLOBAL.ASAX

copia este método después del método de Application_Start

public void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {           
            HttpCookie cookie = Request.Cookies["Usuario"];
            if (cookie != null)
            {              
                string datos = cookie.Value;           
                FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(datos);              
                string role = ticket.UserData;
                GenericPrincipal principal = new GenericPrincipal(new GenericIdentity(ticket.Name), new string[] { role });
                HttpContext.Current.User = principal;
            }
        }

Ultimo paso, aplicar el [Autorizar] en cualquier ACTION CONTROLADOR que quiere aplicarse la autenticación de seguridad.

Con esto cuando el usuario quiere acceder al ACTION que has aplicado la autenticación el proyecto va ha pedir que primero se inicia la sesión.

1º_post_60

Si tiene cualquier duda vuelva al Principio de este BLOG Y léalo otra vez Paso a Paso

Volver a Principio

Autor: YIBING JIN

Curso: Microsoft MCSA Web Applications + Microsoft MCSD App Builder + Xamarin

Centro: Tajamar

Año académico: 2019-2020

Linkedin Repository GITHUB

Leave a Comment

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

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.