1

我正在为 ASP.NET MVC 2 中的特许经营服务业务构建基于 Web 的 CRM + CMS 的第二次迭代。我需要根据用户为该特许经营分配的角色来控制对每个特许经营服务的访问。

4个例子:

  • Receptionist应该能够为她的“大西洋海岸”特许经营权预订服务工作,但不做任何报告。
  • Technician应该能够更改服务工作,但不能修改发票。
  • Managers应该能够为其商店内的工作发票应用折扣。
  • Owner应该能够提取他拥有的任何特许经营权的报告。

特许经营级别的访问控制应该在Data - Services - Web层之间的什么位置?
如果它属于我的控制器,我应该如何最好地实现它?

部分模式

Roles班级

int ID { get; set; } // primary key for Role
string Name { get; set; }

部分Franchises

short ID { get; set; } // primary key for Franchise
string Slug { get; set; } // unique key for URL access, eg /{franchise}/{job}
string Name { get; set; }

UserRoles映射

short FranchiseID; // related to franchises table
Guid UserID; // related to Users table
int RoleID; // related to Roles table
DateTime ValidFrom;
DateTime ValidUntil;

控制器实现

[Authorize]带属性的访问控制

如果只涉及一个特许经营权,我可以简单地限制对控制器操作的访问,如下所示:

[Authorize(Roles="Receptionist, Technician, Manager, Owner")]
public ActionResult CreateJob(Job job)
{
    ...
}

而且由于特许经营权不会在一夜之间突然出现,也许这是使用ASP.NET MVC 2 中的新区域功能的一个强有力的案例?或者这会导致重复的视图?

控制器、URL 路由和区域

假设不使用区域,确定正在访问哪个特许经营权数据的最佳方法是什么?我想到了这个:

{franchise}/{controller}/{action}/{id}

还是在 Details(...) 操作中确定工作的特许经营权并使用 [Authorize] 限制用户的操作是否更好:

{job}/{id}/{action}/{subaction}
{invoice}/{id}/{action}/{subaction}

如果任何用户都可以访问多个特许经营权而不会使用 {franchise} 参数混淆 URL,那么这更有意义。

任何输入表示赞赏。

编辑:

背景

我用经典的 ASP 构建了以前的 CRM,它运行良好,但现在是时候进行升级以加快工作流程并减少出错空间。为了正确测试和更好地分离数据和表示,我决定实现存储库模式,如 Rob Conery 的 MVC Storefront 系列中所示。

如何安排服务和存储库?

JobService有一个基于可用过滤器检索任何服务作业的a 是有意义的,例如。IQueryable<Job> GetJobs();. 但是由于一项工作只能属于一个特许经营权,因此类似的功能IQueryable<Job> GetJobs(int franchiseID);可能属于其中之一FranchiseServiceJobService. 应该FranchiseService充当CatalogService(就像在 MVC Storefront 中一样)?

4

1 回答 1

0

让我尝试回答这个问题。我正在玩一个涉及上述某些方面的示例应用程序。这不是一个权威的答案,只是经验。

特许经营级别的访问控制应该在数据 - 服务 - Web 层之间适合什么地方?

这种访问限制应该贯穿您的应用程序的两个级别:1)数据库 2)应用程序层。在 MVC 上下文中,我建议创建一个自定义授权属性 - 这处理 Web 服务层之间的安全性。我会让这个属性做两件事

  1. 获取用户当前允许的角色(从它的数据库中可以存储在用户会话中)
  2. 执行检查以查看用户是否是允许的角色列表的一部分。关于数据库,这取决于您存储数据的方式,一个数据库用于所有特许经营权或每个特许经营权的数据库。在第一种情况下,有几种方法可以限制和设置对特定特许经营权的数据的访问限制。

由于特许经营权不会在一夜之间突然出现,也许这是使用 ASP.NET MVC 2 中的新区域功能的一个强有力的案例?或者这会导致重复的视图?

我认为应该使用区域来拆分和分组功能。如果您要使用区域来拆分特许经营权,我会在此处看到重复的视图、控制器等。重复视图可以通过使用自定义视图引擎来专门覆盖 MVC 定位视图的方式来克服。插件:查看我对ASP.NET MVC的回答:每个域的定制设计

假设不使用区域,确定正在访问哪个特许经营权数据的最佳方法是什么?

如上所述,您可以在用户会话中存储基本信息,例如用户所属的特许经营权和分配的角色等。我认为我在某处读到的规则是“保护你的行为,而不是你的控制器

为规范而不是例外创建路线等。例如。目前是否有商业案例表明用户可以访问多个特许经营权?

如何安排服务和存储库?

拥有一组基础服务或基础类,其中包含特定特许经营权所需的所有信息,例如franchiseId. 它确实解决的主要问题是您的服务方法更干净,没有franchiseId参数。然而,存储库可能需要这个值,因为在某些时候您需要消除您请求或存储的数据的歧义(假设所有特许经营权都有一个数据库)。但是,您可以使用 IoC 克服其中的一些问题。

我看到的缺点是每次创建对象时总会调用数据库(即,如果franchise 要使用路由,则每次创建服务对象时都需要去数据库获取相应的franchiseId . (我可能在这方面弄错了,因为 IoC 容器确实有一些生活方式选项可以帮助和防止这种情况发生)您可以有一个在您应用程序启动时创建的特许经营权列表,您可以使用它来映射您的路由值来获取正确的信息,这部分答案比较分散,但主要是IoC会帮你解耦很多依赖。

希望这可以帮助..

于 2010-04-28T11:12:38.517 回答