我想知道如何确保员工无法访问其他公司的信息。这不是关于将角色或权限应用于操作的基于身份验证/角色的问题,而是确保某人尝试访问的数据实际上属于他们。
用户属于某个部门,而该部门又属于公司。在下面的示例中,日历属于公司。如何确保用户只能在自己公司内编辑日历。
public ActionResult Edit(int? calendarId)
{
...
}
因此,当用户浏览/ Calendars / 55时,如何确保日历属于与用户相同的公司?因此,例如,您不能篡改URL并为属于另一家公司的日历添加ID。
方法1
public ActionResult Edit(int? calendarId)
{
// get company that calendar belongs to
int calCompanyId = ..
if (CurrentUser.CompanyId != calCompanyId)
return RedirectToAction(....); // cannot access resource
...
}
虽然这会起作用,但我想知道是否有更好的方法来处理这类问题。可能这不需要对所有控制器中的每一个动作进行检查。
是否存在用于解决此类问题的典型模式,您需要检查用户是否可以访问特定路径?我认为这对于拥有资源(公司,部门等)的应用程序来说是一个非常典型的问题,需要确保一个公司/用户无法访问其他公司的数据。
修改
正如@jfar所指出的,我可以使用CompanyId,但在大多数路线中都没有。我是否应该考虑改变我的路线结构,以便始终包含这些以使这些检查更容易?这样做是相当多的工作,但可能会“改变”路线。
在进一步思考这个问题之后,我认为在大多数行动中可能没有其他选择可以使用类似于'IsOwner(....)'的检查。其原因有两个;
在这个阶段,我想我会有一个'IsOwner'方法与@jfar发布的方法类似,可以检查直接链接到公司的资源是否归该公司所有,同时提供一些重载版本
CompanyOwns(CurrentUser.CompanyId, model);
DepartmentOwns(CurrentUser.departmentId, model);
我的所有数据库模型都实现了一个界面,使得通过id更容易找到它们。
public interface IAmIdentifiable<T>
{
T Id { get; }
}
我可能会考虑为模型添加更多接口,以帮助上述辅助进程,如
public interface IAmOwnedByACompany
{
int CompanyId { get; }
}
public interface IAmOwnedByADepartment
{
int DepartmentId { get; }
}
这将使通过反射检查'IsOwner'类型方法中的对象更容易。我没有时间完全考虑这一点,但相信@jfar是正确的,当他在这种情况下说,在确定用户是否应该访问某个特定方法时,您确实需要对每种方法进行某种形式的手动检查route(代表资源)。通过实现一些接口和一些聪明的'IsOwner'类型方法,我希望这些检查非常简单。
答案 0 :(得分:0)
您可以将其添加到基本控制器中。如果名为{CompanyId}的RouteParameter进入,则每个请求都会自动检查以确保CurrentUser.CompanyId与之匹配。
protected User CurrentUser { get; set; }
protected override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
if( RouteData.Values["CompanyId"] != null )
if (CurrentUser.CompanyId != RouteData.Values["CompanyId"] )
//Redirect to wherever
//your not restricted from getting the companyid from the route
//you could get the id from the logged in user, session, or any other method
}
更新
您可以创建一个使用反射来检查实体是否拥有正确所有者的帮助器。即时编写的代码可能会出错。
public bool IsOwner<T>(T model, int companyId)
{
var prop = model.GetType().GetProperty("CompanyId");
if (prop == null)
return false;
var modelCompanyId = (int)prop.GetValue(model, null);
return modelCompanyId == companyId;
}