5

我已经了解 ASP.NET MVC 中基于用户和角色的安全性。但现在我需要一些更细化的东西。

假设我有一个文档列表,其中一些用户已获得授权,有些则没有。每个文档在数据库的文档表中都有对应的记录。如果用户具有安全访问权限,则可以下载文档以供查看。如果您有角色,也可以添加文档。每个文档都有一个 URL,每个文档列表都有一个 URL。

我想安全地修剪列表,以便用户只能看到他被授权的那些文档。但我还需要对这些列表和文档的 URL 请求进行身份验证,因为没有什么可以阻止用户为他们不再有权访问的文档添加书签,或者只是在浏览器中输入 URL。

内置的基于角色的安全模型是否适合于此,或者我是否需要创建单独的基于表的安全性?我可以将安全性放在我的存储库中,以便返回的记录已经被修剪,还是应该是控制器的一部分?我需要一个安全属性来验证控制器请求,还是应该将它作为前几行代码放在控制器方法中?

4

2 回答 2

1

@Robert,当您说应该(在)它们到达视野之前修剪它们时,我认为您已经回答了自己的问题。因此,在您的业务逻辑中,作为对存储库的偏好,您可能想要做一个 lamda 来修剪多余的东西。

我认为我永远不会将任何记录返回给不允许用户查看的视图。为什么要增加风险和流量?

至于书签,我认为您将需要执行一些业务逻辑,以防止它们在访问不再存在时访问 url。

我认为控制器只是在那里为页面提供数据服务,并且没有任何逻辑,所以我更喜欢这个业务层方法,因为它看起来确实是一个业务规则。

这可能不是您的想法,但除非有更好的方法,否则我会使用它。

于 2009-10-05T20:57:24.383 回答
1

我将尝试解释我打算如何在我的项目中实现这一点。要求与您的要求相似:用户具有具有权限的角色,并且所有内容都可以从权限定义、角色的权限列表和用户的角色列表等中更改。因此,在某一时刻,用户可能有权访问某些内容,而在另一时刻,如果管理员更改东西,他没有访问权限。

在我放一些代码之前,我会回答你的问题。

我是否需要创建单独的、基于表格的安全性?

-是的

我可以将安全性放在我的存储库中,以便返回的记录已经被修剪,还是应该是控制器的一部分?

-我认为安全应该是业务逻辑的一部分,所以我会把它放在控制器和存储库之间的某个地方。

我是否需要安全属性来验证控制器请求?

-在我的项目中,我把它放在了属性中,但有时我需要从控制器访问它,但是由于我将安全逻辑保留在业务层中,我认为这不是问题。

第一个属性是简单的属性,只允许登录用户执行操作:

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;
    }
}

然后我有,例如,只允许超级用户访问它的属性:

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());
            }
        }
    }
}

MyBaseController 是继承 Controller 的类,并且有一个 Model 类的实例,代表业务对象的容器。在控制器动作正文中,如果需要,我检查当前实体的用户权限,并根据该权限返回正确的视图:

    [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");     
    }

ps 我不确定我是否可以向显然比我有更多经验的人提出任何建议:),所以如果我在发送垃圾邮件,我对此表示歉意。

于 2009-10-05T21:48:02.227 回答