6 Replies - 2368 Views - Last Post: 25 January 2012 - 12:25 PM

Topic Sponsor:

#1 webwired  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 31
  • View blog
  • Posts: 330
  • Joined: 26-August 07

Create Custom Authorization for MVC 3 or 4

Posted 20 January 2012 - 01:32 PM

Hello everyone...

I am trying to build a custom Authorization system to work with my new MVC web apps... What I would like to do is kind of like the built in Account system, but instead of all of that, I simply want to control access to Controllers and Action Methods...

Here's what I was thinking for my database:

[DATABASE_SCHEMA]
Users
UserID (int, Identity, Primary Key)
UserName (nvarchar 25)
UserPassword (nvarchar 25)
UserEmail (nvarchar 100)

Directories
DirectoryID (int, Identity, Primary Key)
Directory (nvarchar 256, Unique)

UsersDirectoriesAndPermissions
UsersDirectoriesAndPermissionsID (int, Primary Key)
UserID (int, Foreign Key)
DirectoryID (int, Foreign Key)
UserCreate (bit)
UserRetrieve (bit)
UserUpdate (bit)
UserDelete (bit)
[/DATABASE_SCHEMA]

Instead of using [Authorize], [Authorize(Roles = "Admin, Super User")], and [Authorize(Users = "Betty, Johnny")] ... I would use something like this:

[PermitAccess] ==> Which would ensure that the user is logged in from the Users table

[PermitAccess(Directory = "aDirectoryName")] ==> Which would check the UsersDirectoriesAndPermissions table to see if the user has permission to access this directory/Controller (This would be implemented at the Controller level.)

[PermitAccess(Permissions = "Create", "Retrieve", "Update", "Delete")] ==> Which would check the UsersDirectoriesAndPermissions table to see if the user has the appropriate permissions to access this Action Method (This would be implemented at the Action Method level.)

Could anybody help me out with building this?

Is This A Good Question/Topic? 0
  • +

Replies To: Create Custom Authorization for MVC 3 or 4

#2 Sergio Tapia  Icon User is offline

  • Is that a raincoat?
  • member icon

Reputation: 1012
  • View blog
  • Posts: 3,816
  • Joined: 27-January 10

Re: Create Custom Authorization for MVC 3 or 4

Posted 23 January 2012 - 04:23 PM

Something like this would do the trick.

First, wire up your custom filter attribute on the controller / action level:

[PermitAccess(Directories = "aDirectoryName, foo, bar, baz")]
public class Foo : Controller {
    // Your actions here.

    // Note that you can also protect each individual action in the same way.
}


Next you have to create your own filter attribute. Create a folder called Filters on the project root, then add in a new class. Something like this:

public class PermitAccessAttribute : ActionFilterAttribute
    {
        public string Directories{ get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var loggedInUser = repositoryFoo<User>.FindById(filterContext.HttpContext.User.Identity.Name);
            
            var permissions = repository<User>.FindPermissionsForUser(loggedInUser.UserId);

            foreach (string definedDirectory in this.Directories.Split(','))
            {
                foreach (string permission in permissions)
                {
                    if (definedDirectory.Equals(permission))
                        return;
                }
            }

            throw new SecurityException("Access not granted!");
        }
    }


Let me know if you need more assistance.

This post has been edited by Sergio Tapia: 23 January 2012 - 04:39 PM

Was This Post Helpful? 0
  • +
  • -

#3 webwired  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 31
  • View blog
  • Posts: 330
  • Joined: 26-August 07

Re: Create Custom Authorization for MVC 3 or 4

Posted 24 January 2012 - 08:08 AM

View PostSergio Tapia, on 23 January 2012 - 05:23 PM, said:

Something like this would do the trick.

First, wire up your custom filter attribute on the controller / action level:

[PermitAccess(Directories = "aDirectoryName, foo, bar, baz")]
public class Foo : Controller {
    // Your actions here.

    // Note that you can also protect each individual action in the same way.
}


Next you have to create your own filter attribute. Create a folder called Filters on the project root, then add in a new class. Something like this:

public class PermitAccessAttribute : ActionFilterAttribute
    {
        public string Directories{ get; set; }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var loggedInUser = repositoryFoo<User>.FindById(filterContext.HttpContext.User.Identity.Name);
            
            var permissions = repository<User>.FindPermissionsForUser(loggedInUser.UserId);

            foreach (string definedDirectory in this.Directories.Split(','))
            {
                foreach (string permission in permissions)
                {
                    if (definedDirectory.Equals(permission))
                        return;
                }
            }

            throw new SecurityException("Access not granted!");
        }
    }


Let me know if you need more assistance.


I went ahead and continued without the custom system, but I'll open a new project and see if I can get this to work, 'cause it would be nice to have... I'll let you know how it goes...
Was This Post Helpful? 0
  • +
  • -

#4 Sergio Tapia  Icon User is offline

  • Is that a raincoat?
  • member icon

Reputation: 1012
  • View blog
  • Posts: 3,816
  • Joined: 27-January 10

Re: Create Custom Authorization for MVC 3 or 4

Posted 24 January 2012 - 07:55 PM

I read your email, so I made this video. Hopefully it gives you a nudge in the right direction.


Was This Post Helpful? 0
  • +
  • -

#5 webwired  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 31
  • View blog
  • Posts: 330
  • Joined: 26-August 07

Re: Create Custom Authorization for MVC 3 or 4

Posted 24 January 2012 - 08:29 PM

View PostSergio Tapia, on 24 January 2012 - 08:55 PM, said:

I read your email, so I made this video. Hopefully it gives you a nudge in the right direction.


I don't know what to say except, Thank You very much... That's Awesome!
Was This Post Helpful? 0
  • +
  • -

#6 webwired  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 31
  • View blog
  • Posts: 330
  • Joined: 26-August 07

Re: Create Custom Authorization for MVC 3 or 4

Posted 25 January 2012 - 10:46 AM

View PostSergio Tapia, on 24 January 2012 - 08:55 PM, said:

I read your email, so I made this video. Hopefully it gives you a nudge in the right direction.


I'd love to see your Register controller action method, because right now I can't get a user registered, using my own table instead of theirs...

EDIT: On second thought, forget it, I appreciate your help, but there seems to be good reason why MVC forums have no user base, because until they get their shit straight and finish developing MVC so that it's actually usable, there's no sense in getting started with it... I mean MVC itself is wonderful, IMO, but if you can't even set up a Membership system, then you can't go anywhere...

This post has been edited by webwired: 25 January 2012 - 11:39 AM

Was This Post Helpful? 0
  • +
  • -

#7 Sergio Tapia  Icon User is offline

  • Is that a raincoat?
  • member icon

Reputation: 1012
  • View blog
  • Posts: 3,816
  • Joined: 27-January 10

Re: Create Custom Authorization for MVC 3 or 4

Posted 25 January 2012 - 12:25 PM

The MVC framework has been in development for YEARS now and it's a fantastic framework to use. It actually turned me on to the idea of web programming. If you're sure you don't want to use ASP.Net MVC, you might want to use regular ASP.Net Webforms.

Be warned that your pages will be incredibly bloated and full of boilerplate HTML, CSS and javascript interweaved.

For a small project, I can have 16KB of HTML down the wire with MVC, but with Webforms you're looking at 180KB+ for the same thing. Just keep that in mind.

You might want to try using something like Ruby on Rails. It's more set it and forget with a lot of common functionality built in already.

Edit: Here's the controller for registering and logging in a user. It's very simple, check it out for ideas.

    public class CuentaController : Controller
    {
        private readonly IUsuarioRepository _iUsuarioRepository;

        public CuentaController(IUsuarioRepository iUsuarioRepository)
        {
            _iUsuarioRepository = iUsuarioRepository;
        }
        
        public ActionResult IniciarSesion()
        {
            return View();
        }

        [HttpPost]
        public ActionResult IniciarSesion(LogOnModel model)
        {
            if (ModelState.IsValid)
            {
                if (_iUsuarioRepository.ValidarCuenta(model.Correo, model.Contrasena))
                {
                    FormsAuthentication.SetAuthCookie(model.Correo, true);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    ModelState.AddModelError("", "El correo y/o contraseña estan incorrecto.");
                    return View(model); 
                }
            }

            return View(model);
        }

        public ActionResult CerrarSesion()
        {
            FormsAuthentication.SignOut();
            return RedirectToAction("Index", "Home");
        }

        public ActionResult Crear()
        {
            UsuarioModel model = new UsuarioModel();

            EfLocalidadRepository localidadRepo = new EfLocalidadRepository();
            model.Localidad = new List<SelectListItem>();

            foreach (var localidad in localidadRepo.FindAllLocalidad())
            {
                model.Localidad.Add(new SelectListItem { Text = localidad.Nombre, Value = localidad.LocalidadId.ToString(), Selected = false });
            }

            return View(model);
        }

        [HttpPost]
        public ActionResult Crear(UsuarioModel model)
        {
            EfLocalidadRepository localidadRepo = new EfLocalidadRepository();
            model.Localidad = new List<SelectListItem>();

            foreach (var localidad in localidadRepo.FindAllLocalidad())
            {
                model.Localidad.Add(new SelectListItem { Text = localidad.Nombre, Value = localidad.LocalidadId.ToString(), Selected = false });
            }

            //Save the users information.
            if (ModelState.IsValid)
            {
                Domain.Usuario nuevoUsuario = new Usuario();
                nuevoUsuario.LocalidadId = model.LocalidadId;
                nuevoUsuario.Empresa = model.Empresa;
                nuevoUsuario.Direccion = model.Direccion;
                nuevoUsuario.PaginaWeb = model.PaginaWeb;
                nuevoUsuario.Telefono = model.Telefono;
                nuevoUsuario.Nombre = model.Nombre;
                nuevoUsuario.Apellidos = model.Apellidos;
                nuevoUsuario.FechaDeNacimiento = Convert.ToDateTime(model.FechaDeNacimiento);
                nuevoUsuario.CorreoElectronico = model.CorreoElectronico;
                nuevoUsuario.Cargo = model.Cargo;
                nuevoUsuario.TelefonoMovil = model.TelefonoMovil;
                nuevoUsuario.Contrasena = model.Contrasena;

                var result = _iUsuarioRepository.CrearCuenta(nuevoUsuario);

                if (result == EfUsuarioRepository.ResultadoCreacionUsuario.Ok)
                {
                    FormsAuthentication.SetAuthCookie(model.CorreoElectronico, false);
                    return RedirectToAction("Index", "Home");
                }
                else
                {
                    switch (result)
                    {
                        case EfUsuarioRepository.ResultadoCreacionUsuario.CorreoExiste:
                            ModelState.AddModelError("", "Ese correo ya esta en uso.");
                            break;
                        case EfUsuarioRepository.ResultadoCreacionUsuario.ErrorDesconocido:
                            ModelState.AddModelError("", "Algo sucedio durante el registro. Por favor intente de nuevo.");
                            break;
                        default:
                            break;
                    }
                }
            }

            return View(model);
        }

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


This post has been edited by Sergio Tapia: 25 January 2012 - 12:26 PM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1