Document-Based Security in ASP.NET MVC

后端 未结 2 1611
忘了有多久
忘了有多久 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:30

    @Robert, I think you've already answered your own question when you said you should trim them (before) they reach the view. So in your Business logic, as a preference over the repository, you might want to do a lamda to trim off the excess so to speak.

    Im my opinion I would never return any records to the view that the user wasn't allowed to see. Why increase risk and traffic?

    As for the bookmarks I think there you're going to need to do some business logic preventing them from going to the url when access no longer exists.

    I thought the controller was simply there to service the data to the page and not to have any logic as such so I'd prefer the business layer approach for this one as it does appear to be a business rule.

    That might not be what you had in mind but unless there is a better approach it's the one I would use.

    0 讨论(0)
  • 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.

    0 讨论(0)
提交回复
热议问题