Vediamo come implementare un semplice CustomRoleProvider con Microsoft Visual Studio e C#.
web.config
Nel web.config si deve inserire la configurazione per usare il CustomRoleProvider nel sistema:
<system.web>
...
<roleManager enabled="true" cookieTimeout="20" defaultProvider="CustomRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider" type="My.NameSpace.CustomRoleProvider, My.NameSpace" />
</providers>
</roleManager>
...
</system.web>
CustomRoleProvider
Questa è la classe che gestisce i ruoli:
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
namespace My.NameSpace
{
public class CustomRoleProvider : RoleProvider
{
#region Attributes
private string pApplicationName = "MyApplication";
public override string ApplicationName
{
get { return pApplicationName; }
set { pApplicationName = value; }
}
#endregion Attributes
#region Constructors
public CustomRoleProvider() : base()
{
}
#endregion Constructors
#region Methods
public override void AddUsersToRoles(string[] usernames, string[] roleNames)
{
throw new System.NotImplementedException();
}
public override void CreateRole(string roleName)
{
throw new System.NotImplementedException();
}
public override bool DeleteRole(string roleName, bool throwOnPopulatedRole)
{
throw new System.NotImplementedException();
}
public override string[] FindUsersInRole(string roleName, string usernameToMatch)
{
throw new System.NotImplementedException();
}
public override string[] GetAllRoles()
{
//Questa è la lista di tutti i ruoli gestita
return new string[] { "Administrator", "Ruolo 1" };
}
public override string[] GetRolesForUser(string username)
{
//TODO questo metodo va implementato estraendo i ruoli per l'utente passato dal DB o da altra fonte
throw new System.NotImplementedException();
}
public override string[] GetUsersInRole(string roleName)
{
throw new System.NotImplementedException();
}
public override bool IsUserInRole(string username, string roleName)
{
return GetRolesForUser(username).Contains(roleName);
}
public override void RemoveUsersFromRoles(string[] usernames, string[] roleNames)
{
throw new System.NotImplementedException();
}
public override bool RoleExists(string roleName)
{
return GetAllRoles().Contains(roleName);
}
#endregion Methods
}
}
Controller
Se si vuole controllare nel controller l'accesso baato su ruoli ad un determinato metodo:
[HttpGet]
[AuthorizeRoles("Administrator", "Ruolo 1")]
public ActionResult MyMethod()
{
return View("...myView.cshtml", cm);
}
AuthorizeRolesAttribute
Questa classe implementa un nuovo attributo con cui taggare i metodi del controller:
using System;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace My.NameSpace
{
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AuthorizeRolesAttribute : AuthorizeAttribute
{
public string RedirectActionName { get; set; }
public string RedirectControllerName { get; set; }
public AuthorizeRolesAttribute(params string[] roles) : base()
{
Roles = string.Join(",", roles);
}
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated || filterContext.HttpContext.Session["UserRoles"] == null)
{
filterContext.Result = new RedirectResult("~/Account/Logoff");
}
}
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
var provider = new CustomRoleProvider();
if (!httpContext.User.Identity.IsAuthenticated)
return false;
//var roles = provider.GetAllRoles();
var roles = this.Roles.Split(',');
var rolesUser = provider.GetRolesForUser(httpContext.User.Identity.Name);
if (roles != null && roles.All(role => rolesUser.Contains(role)))
{
return true;
}
return base.AuthorizeCore(httpContext);
}
}
}