I have an authorization requirement to have my security roles based on actions methods, which can not be achieved using the default asp.net mvc authorization. so i have created the following action filter, to implement my custom authorization requirments:-
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class CheckUserPermissionsAttribute : ActionFilterAttribute
{
Repository repository = new Repository();
public string Model { get; set; }
public string Action { get; set; }
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// var user = User.Identity.Name; // or get from DB
string ADusername = filterContext.HttpContext.User.Identity.Name.Substring(filterContext.HttpContext.User.Identity.Name.IndexOf("\\") + 1);
if (!repository.can(ADusername,Model,Action)) // implement this method based on your tables and logic
{
filterContext.Result = new HttpUnauthorizedResult("You cannot access this page");
}
base.OnActionExecuting(filterContext);
}
}
which is calling the following Repository method:-
public bool can(string user, string Model, string Action)
{
bool result;
bool result2;
int size = tms.PermisionLevels.Where(a5 => a5.Name == Action).SingleOrDefault().PermisionSize;
var securityrole = tms.SecurityroleTypePermisions.Where(a => a.PermisionLevel.PermisionSize >= size && a.TechnologyType.Name == Model).Select(a => a.SecurityRole).Include(w=>w.Groups).Include(w2=>w2.SecurityRoleUsers).ToList();//.Any(a=> a.SecurityRoleUsers.Where(a2=>a2.UserName.ToLower() == user.ToLower()));
foreach (var item in securityrole)
{
result = item.SecurityRoleUsers.Any(a => a.UserName.ToLower() == user.ToLower());
var no = item.Groups.Select(a=>a.TMSUserGroups.Where(a2=>a2.UserName.ToLower() == user.ToLower()));
result2 = no.Count() == 1;
if (result || result2)
{
return true;
}}
return false;
i am calling the action filter inside my controller class as follow:-
[CheckUserPermissions(Action = "Read", Model = "Server")]
but i have the following concerns:-
inside my repository i will be retrieving all the users and groups (when calling the .Tolist()), and then check if the current login user is inside these values. which will not be very extensible when dealing with huge number of users?
each time the user call an action method the same security code will run (of course ideally the user permission might chnage during the user session),,, which might cause performance problems ?
So can anyone adice how i can improve my current implementation, taking the two concerns in mind ? Thanks