none
Como asignar permisos a usuarios para determinadas acciones?

    Question

  • Hola,

    De ante mano, agradecería que me puedan ayudar en lo siguiente;

    (IDE: MS Visual Web Developer Express 2010, Framework: ASP.NET MVC 3, utilizo razor en los controles)

    Necesito crear una aplicación web en la cual requiero hacer un modulo de permisos de usuarios para que un determinado usuario pueda resalizar o no ciertas acciones según los permisos que le otorgue el administrador del sistema, tales permisos son como; buscar, actualizar, eliminar, exportar datos, etc. en la imagen detallo la maqueta de interfaz de usuario que podria hacer, he investigado el tema del atributo Authorize que incluye ASP.NET MVC, y en unos ejemplos vi que a lo mejor lo podria realizar de esta forma;

    [AuthorizedOnly(Roles="admin", Users="DinoE")]
    public ActionResult Index()
    {
    ...
    }

    pero al consultar por el permiso de un usuario como podría asignar el valor recuperado de dicha consulta y asignársela a la propiedad Authorise?

    , la mayor experiencia que tengo es en window form y hay esto mismo lo aplico de la siguiente forma;

    en el evento load del formulario, consulto por el permiso:

    botonEliminar.enable=ConsultaPermisos(usuario)' esto retorna un valor boolean y segun la consuta habilita o no el control

    bueno aquí me surge otra inquietud, como realizar algo similar si es que se puede en ASP.NET MVC?

    Espero haberme explicado, cualquier duda daría mas detalles.

    a la espera de alguna sugerencia o ayuda

    saludos


    Mauricio Hernández A.

    Thursday, December 13, 2012 10:16 PM

All replies

  • Hola.

    Pues se que con membership ya viene algo de esto, pero es muy invasivo para mi gusto.

    Una vez estructurada tu base de datos, la parte de la seguridad en el MVC la puedes lograr haciendo uso de FormsAuthenticationTicket ... algo como muestran en este aporte en Stack Overflow

    Saludos.


    Nicolás Herrera
    Bogotá - Colombia
    BLOG | @nicolocodev
    "Daría todo lo que sé, por la mitad de lo que ignoro." Rene Descartes

    Saturday, December 15, 2012 6:22 AM
  • Con Membership provider puedes "resolver" todas esas situaciones...

    Claro si lo haces a mano, si utilizas la herramienta de administración (o como se llame), mejor olvídate.. es algo que yo no veo nada bueno.

    La mejor manera (a mi gusto) crear tus propias clases para manejarlo, pero siempre utilizando la cookie de autenticación ahi si que puedes hacer funcionar el Authorize, ojo nada de variables de session!.

    De cualquier forma, depende que tanto intentes extenderte con Membership (si es que lo utilizas), puedes ver ésta discusión en LinkedIn: http://www.linkedin.com/groups/Usar-no-usar-modelo-Membership-3889150.S.72871332

    Saludos!


    Miguel Salazar
    -> Thanks Network!

    Saturday, December 15, 2012 8:09 AM
  • Hola,

    Gracias por responder, investigare lo sugerido para probar alternativas. ya que se ve bastante amplio el tema.

    Saludos


    Mauricio Hernández A.

    Monday, December 17, 2012 2:49 AM
  • Yo hice algo parecido a lo que necesitas. Lo hice fue implementar las clases abstractas AuthorizeAttribute e IIdentity.

    public class MyAuthorizeAttribute : AuthorizeAttribute {

    // Codigo del permiso a evaluar public int PermisoRequerido { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException("httpContext"); if (httpContext.User.Identity.IsAuthenticated == false) return false; try {

    // Implementación personalizada de IIdentity IdentidadUsuario identidad = (IdentidadUsuario)HttpContext.Current.User.Identity; return identidad.Permisos.Contains(PermisoRequerido.ToString()); } catch (Exception) { return false; } } }

    El IIdentity va así:

        public class IdentidadUsuario : IIdentity
        {
    
            public IdentidadUsuario(string name, string permisos)
            {
                IsAuthenticated = true;
                Name = name;
                AuthenticationType = "Forms";
    
                Permisos = permisos;
            }
    
            public string AuthenticationType { get; private set; }
            public bool IsAuthenticated { get; private set; }
            public string Permisos{ get; private set; }
        }

    En el controlador lo que hago es usar el helper que se creó para filtrar en cada acción o en cada control, depende de como quieras hacer el control de permisos:

        [MyAuthorizeAttribute(PermisoRequerido = 1)]
        public class ClienteController : Controller
        {
        }


    En el logon de tu aplicación debes adicionar dentro de tu cookie de cache la información de los permisos:

    StringBuilder permisos = new StringBuilder();
    
    foreach(string permiso in repository.getPermisos(UsuarioID))
    {
    permisos.Append(string.Format("{0},", permiso ));
    }
    
    
                        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket
                            (1,                             // Versión ticket
                            usuario.Descripcion,            // Nombre del usuario autenticado
                            DateTime.Now,                   // Fecha de emisión
                            DateTime.Now.AddMinutes(30),    // Fecha de expiración
                            false,                          // Verdadero si se desea que persista entre sesiones del navegador
                            permisos.ToString());           // Datos adicionales
    
                        //Se hace la encriptación del ticket
                        string encryptedTicket = FormsAuthentication.Encrypt(ticket);
    
                        // Se adicciona la cookie al request para salvarlo
                        HttpCookie cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                        cookie.HttpOnly = true;
                        Response.Cookies.Add(cookie);

    Por último en el global.asax creas este metodo:

            protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
            {
                if (Request.IsAuthenticated)
                {
                    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
                    if (authCookie != null)
                    {
                        // Se extrae la cookie de autenticación
                        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    
                        // Se crea una instancia IIdentity identidad
                        IdentidadUsuario identidad = new IdentidadUsuario(authTicket.Name, authTicket.UserData);
    
                        // Se crea el IPrinciple
                        // Todo: Lo correcto es cargar los   permisos en el array de string del IPrinciple pero cuando me di cuenta de esto ya lo habia implementado en el UserData
                        GenericPrincipal principal = new GenericPrincipal(identidad, new string[] { });
    
                        // Se configura el contexto
                        Context.User = principal;
                    }
                }
            }

    Como funciona todo esto:

    Cuando haces el logueo guardas la información de los permisos y cualquier otra que desees almacenar en la cookie de autenticación (la información adicional la almacenas usando el parametro que tengo como datos adicionales, lo que yo hago es por ejemplo codificar esa cadena algo así "ID:1|Nombre:David|Permisos:1,2,5", por seguridad no se debe guardar información que comprometa la seguridad de la aplicación, solo datos que es bueno tenerlos a mano sin necesidad de consultar la base de datos, en este ejemplo sólo guardé los códigos de los permisos). Antes de cargar cualquier controlador, el FW de MVC corre el metodo que se creó en el global.asax, aquí cargamos los datos de autenticación y decodificamos los datos adicionales usando la implementación personalizada del  IIdentity. El filtro MyAuthorizeAttribute (que es una clase personalizada del Authorize) lo que hace es usar la clase que personalizamos del IIdentity para determinar si el usuario tiene o no los permisos para usar la acción o el controlador al que se lo apliques.

    Revisa estos blogs, hay buena información de autorización y autenticacion que puede complementar la info que te dí.

    http://www.brianlegg.com/post/2011/05/09/Implementing-your-own-RoleProvider-and-MembershipProvider-in-MVC-3.aspx

    http://geeks.ms/blogs/etomas/archive/2010/12/16/asp-net-obtener-el-id-del-usuario-actual.aspx


    Monday, December 17, 2012 5:28 PM
  • Hola David,

    Gracias por la información, he quedado un poco mas claro con la explicación expuesta

    como estoy recién empezando en ASPNET MVC, implementare esto en el ejemplo de mvcMovie.

    y creo que saldrán mas dudas. estaré consultando!

    saludos


    Mauricio Hernández A.


    • Edited by mauriciohz Monday, December 17, 2012 6:50 PM falta info...
    Monday, December 17, 2012 6:47 PM