Document-Based Security in ASP.NET MVC

后端 未结 2 1622
忘了有多久
忘了有多久 2020-12-29 00:27

I already know about User and Role-based security in ASP.NET MVC. But now I need something a little more granular.

Let\'s say I have a list of documents, some of wh

2条回答
  •  庸人自扰
    2020-12-29 00:50

    I'll try to explain how I intended to implement this in my project. The requirement is similar as yours: Users have Roles which have Permissions and everything can change from Permission definition, Role's Permission list, and User's Role list etc. So in one moment it's possible that User has access to something and in another, if Administrator alter something, he does not have access.

    Before I put some code, I'll answer to your questions.

    Do I need to create separate, table-based security?

    -Yes

    Can I put the security in my repository, so that the returned records are already trimmed, or should it be part of the controller?

    -I think security should be a part of business logic so I would put it somewhere in between controller and repository.

    Do I need a security attribute to validate the controller request?

    -In my project, I've put it in attribute, but sometimes i need to access it from controller to, but since that I keep security logic in business layer, I don't think it is a problem.

    First attribute is simple attribute that just allows logged users to execute action:

    public class LoggedUserFilterAttribute : ActionFilterAttribute
    {
        public bool Logged { get; set; }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            if (!SessionManager.IsUserLogged)
            {
                filterContext.Result = new RedirectToRouteResult(GetRedirectToNotLoggedRouteValues());
                this.Logged = false;
            }
            else
                this.Logged = true;
        }
    
        public RouteValueDictionary GetRedirectToNotAuthorizedRouteValues()
        {
            RouteValueDictionary routeValues = new RouteValueDictionary();
            routeValues.Add("action", "NotAuthorized");
            routeValues.Add("controller", "Authorization");
            return routeValues;
        }
        public RouteValueDictionary GetRedirectToNotLoggedRouteValues()
        {
            RouteValueDictionary routeValues = new RouteValueDictionary();
            routeValues.Add("action", "NotLogged");
            routeValues.Add("controller", "Authorization");
            return routeValues;
        }
    }
    

    and then I have, for example, attribute which allows only SuperUsers to access it:

    public class SuperUserFilterAttribute : LoggedUserFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            base.OnActionExecuting(filterContext);
    
            if (Logged)
            {
                MyBaseController controller = filterContext.Controller as MyBaseController;
                if (controller == null)
                    throw new Exception("Please use MyBaseController instead of built in Controller");
    
                User loggedUser = controller.Model.UserBO.GetUserByID(SessionManager.LoggedUser.UserID);
    
                if(!loggedUser.IsSuperUser)
                {
                    filterContext.Result = new RedirectToRouteResult(GetRedirectToNotAuthorizedRouteValues());
                }
            }
        }
    }
    

    The MyBaseController is class that inherits Controller and has an instance of Model class which represent container for business objects. In controllers action body, if needed I check users rights on current entity and depending on that I return proper view:

        [LoggedUserFilter]
        public ActionResult LoadSomeEntity(int customerServiceID,int entityID)
        {
            UserRights userPermissionsView = Model.SecurityBO.GetUsersRightsOnEntity(SessionManager.LoggedUser.UserID, entityID);
    
            if(userPermissionsView.Write) 
                return View("EditEntity",Model.EntityBO.GetEntityByID(entityID));
            if(userPermissionsView.Read) 
                return View("ViewEntity",Model.EntityBO.GetEntityByID(entityID));
    
            return View("NotAuthorized");     
        }
    

    p.s. I'm not sure if I can suggest anything to someone that obviously has much more experience that me :), so if I'm spamming, I apologize for that.

提交回复
热议问题