net mvc asp active asp.net asp.net-mvc asp.net-mvc-5 windows-authentication asp.net-authorization

active - ASP.NET MVC Cómo crear un proveedor de roles personalizado



windows authentication mvc 5 (1)

Siendo relativamente nuevo en ASP MVC, no estoy seguro de cuál se adaptaría mejor a mis necesidades. Construí un sitio de intranet usando la autenticación de Windows y puedo asegurar los controladores y las acciones usando los roles de Active Directory, por ejemplo

[Authorize(Roles="Administrators")] [Authorize(Users="DOMAIN/User")] public ActionResult SecureArea() { ViewBag.Message = "This is a secure area."; return View(); }

Necesito definir mis propios roles de seguridad independientes de los roles AD. La funcionalidad deseada es que los usuarios autenticados tengan acceso a acciones específicas según uno o más roles asociados con su perfil en la base de datos de mi aplicación, por ejemplo: "Gerente", "Usuario", "Invitado", "Analista", "Desarrollador", etc.

¿Cómo creo un proveedor de rol personalizado y / o atributo (s) de autorización personalizado?

EDITAR: editó el título y la pregunta para que otros usuarios puedan identificar el contenido de la publicación.


Mi solución fue crear un proveedor de roles personalizado. Estos son los pasos que tomé, en caso de que alguien más necesite ayuda más adelante:

Crea tu usuario personalizado y las clases de roles

using Microsoft.AspNet.Identity.EntityFramework; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Security.Models.Security { public class AppRole : IdentityRole { } }

y

using Microsoft.AspNet.Identity.EntityFramework; using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Security.Models.Security { public class AppUser : IdentityUser { } }

Configure su contexto de base de datos

using Microsoft.AspNet.Identity.EntityFramework; using Security.Models.Security; using System; using System.Collections.Generic; using System.Data.Entity; using System.Linq; using System.Web; namespace Security.Models.DAL { public class UserContext : IdentityDbContext<AppUser> { public UserContext() : base("UserContext") { Database.SetInitializer<UserContext>(new CreateDatabaseIfNotExists<UserContext>()); } } }

Crea tu proveedor de roles e implementa los siguientes métodos

using Security.Models.DAL; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Security; namespace Security.Models.Security { public class AppRoleProvider : RoleProvider { public override string[] GetAllRoles() { using (var userContext = new UserContext()) { return userContext.Roles.Select(r => r.Name).ToArray(); } } public override string[] GetRolesForUser(string username) { using (var userContext = new UserContext()) { var user = userContext.Users.SingleOrDefault(u => u.UserName == username); var userRoles = userContext.Roles.Select(r => r.Name); if (user == null) return new string[] { }; return user.Roles == null ? new string[] { } : userRoles.ToArray(); } } public override bool IsUserInRole(string username, string roleName) { using (var userContext = new UserContext()) { var user = userContext.Users.SingleOrDefault(u => u.UserName == username); var userRoles = userContext.Roles.Select(r => r.Name); if (user == null) return false; return user.Roles != null && userRoles.Any(r => r == roleName); } } } }

Edite su web.config para configurar la conexión a la base de datos y la referencia del proveedor de roles

<connectionStrings> <add name="UserContext" connectionString="Data Source=(LocalDb)/MSSQLLocalDB;AttachDbFilename=|DataDirectory|/UserContext.mdf;Initial Catalog=UserContext;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> </connectionStrings>

y

<system.web> ... <authentication mode="Windows" /> <roleManager enabled="true" defaultProvider="AppRoleProvider"> <providers> <clear/> <add name="AppRoleProvider" type="Security.Models.Security.AppRoleProvider" connectionStringName = "UserContext"/> </providers> ... </roleManager> </system.web>

En la consola del administrador de paquetes, habilite las migraciones

enable-migrations

En las Configuraciones.cs recientemente creadas, configure las administraciones y los almacenes de usuarios / roles y configure el validador del administrador de usuarios para aceptar ''/' caracteres

namespace Security.Migrations { using Microsoft.AspNet.Identity; using Microsoft.AspNet.Identity.EntityFramework; using Security.Models.Security; using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; internal sealed class Configuration : DbMigrationsConfiguration<Security.Models.DAL.UserContext> { public Configuration() { AutomaticMigrationsEnabled = true; ContextKey = "Security.Models.DAL.UserContext"; } protected override void Seed(Security.Models.DAL.UserContext db) { // Set up the role store and the role manager var roleStore = new RoleStore<AppRole>(db); var roleManager = new RoleManager<AppRole>(roleStore); // Set up the user store and the user mananger var userStore = new UserStore<AppUser>(db); var userManager = new UserManager<AppUser>(userStore); // Ensure that the user manager is able to accept special characters for userNames (e.g. ''/' in the ''DOMAIN/username'') userManager.UserValidator = new UserValidator<AppUser>(userManager) { AllowOnlyAlphanumericUserNames = false }; // Seed the database with the administrator role if it does not already exist if (!db.Roles.Any(r => r.Name == "Administrator")) { var role = new AppRole { Name = "Administrator" }; roleManager.Create(role); } // Seed the database with the administrator user if it does not already exist if (!db.Users.Any(u => u.UserName == @"DOMAIN/admin")) { var user = new AppUser { UserName = @"DOMAIN/admin" }; userManager.Create(user); // Assign the administrator role to this user userManager.AddToRole(user.Id, "Administrator"); } } } }

En la consola del gestor de paquetes, asegúrese de que la base de datos esté creada y sembrada

update-database

Cree un atributo de autorización personalizado que redirija a una página de acceso denegado en caso de error

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Security.Models.Security { public class AccessDeniedAuthorizationAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); if(filterContext.Result is HttpUnauthorizedResult) { filterContext.Result = new RedirectResult("~/Home/AccessDenied"); } } } }

¡Terminaste! Ahora puede crear una página de acceso denegado (en este caso ~ / Home / AccessDenied) y aplicar el atributo a cualquier acción, por ejemplo

using Security.Models.Security; using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; namespace Security.Controllers { public class HomeController : Controller { ... [AccessDeniedAuthorizationAttribute(Roles = "Administrator")] public ActionResult SecureArea() { return View(); } public ActionResult AccessDenied() { return View(); } ... } }

Espero que esto ayude a alguien en el futuro. ¡Buena suerte!