我很好奇MVC 3中数据级安全性的最佳方法。让我画一幅画。
存在一个事件视图。此活动列出了活动的名称以及此活动中玩家正在播放的列表。
根据当前用户与该事件的关系,每个用户都会获得截然不同的视图。
例如,如果用户是管理器,则用户可以查看和管理该事件的所有其他用户可用性。
如果用户仅参与该事件,那么显然该用户只能操纵他自己的可用性。
有更多的组合。
我知道自定义操作过滤器,但这似乎有点过头了。
相反,我已经选择了一种方法,在事件索引上,有一个switch语句将重定向到相应的View,例如OrganiserEventView或PlayerEventView。
这很容易。我想。
它变得混乱的是我使用共享编辑器来枚举PlayerModels(主视图模型的一部分)来列出玩家。这个共享编辑器本身也必须尊重数据级安全性。
我是在正确的轨道上,还是有更好的方法?
答案 0 :(得分:3)
邓肯,
这是我在每个应用程序中遇到的问题。以下是一些背景信息:我在大学的一个部门工作,因此我们必须处理多个数据源。我们的大多数应用程序都具有集成大学“中央IT”安全服务(如集中身份验证和活动目录)以及“自行开发”角色和权限的安全性。
我们的应用需要根据“自行开发”应用程序(在我们的部门内部使用)和企业数据中的数据,为不同用户提供不同的视图和操作。
我们的方法: 在环顾四周并且没有找到解决这个问题的好方法后,我最终编写了一个安全框架供我们使用。我不妨继续说明它在这里的作用。这是涉及的内容:
此时,这是Asp.Net MVC的示例流程:
- [Inside Permission.IsAllowed] -
为了简化操作,我更进了一步,创建了一个AbstractContextProtectedAttribute,它需要一个可以创建SecurityContext的SecurityContextFactory委托(例如,给定一个HTTPRequest)和一个用指定的SecurityContext检查的权限。然后可以使用此类的子类来装饰控制器操作。
唷!所以,让我现在设置一个用户,角色,权限表并将它们相互映射,定义数据库中的所有权限。我编写了一个可插入的SecurityPersistenceService,它使安全框架与所使用的持久性策略无关 - 我们遗憾地拥有从DataReaders,DataAdapters到Linq2Sql和EF的所有内容。但至少我们可以编写这样的代码:
[Protected("CanAccessX")] // Checks using default context
public class SomeController
{
[Protected("CanSeeY")] // Checks using default context
public PartialViewResult GetY(<parameters>)
{
var canSeeY_Variation1 = Permission.Get("CanSeeY_Variation1") ;
var y_Variation1_Context = new Y_Variation1_Context { <build your context here> } ;
if (canSeeY_Variation1.IsAllowed(y_variation1_Context))
{
<return variation 1 view>
}
// Y_Variation_2...etc
}
}
为了使这项工作,在启动时我注册了适当的验证器:
public class MyNinjectModule
{
public override void Load()
{
// Wire up a persistence service for the security framework
// to use.
SecurityService.SecurityPersistenceService = new MySecurityPersistenceServiceImplementation() ;
// This is what allows the SecurityService to figure out what Validator to use
// in a specified Context to get the User's Roles.
SecurityService.RegisterValidator<Y_Variation1_Context>(new Y_Variation1_ContextValidator(...)) ;
}
}
我现在正致力于增加这个框架,让我对数据的可枚举执行这些检查,从而将我的所有域对象注入安全基础结构。我知道这样做的唯一干净方法是使用AOP。我曾经在Java中工作并使用了AspectJ。现在我正在考虑PostSharp。
希望这为思考你的问题提供了视角。
答案 1 :(得分:1)
答案将根据应用程序的大小,复杂程度和预计增长而变化。虽然在控制器中具有安全性然后具有不同的视图,但是存在权衡。例如,代码/标记复制可能是一个缺点。对于复杂的应用程序,portlet可能会有所帮助,但这很重要。视图可以根据安全性和访问角色进行更改,您可以像控制其他任何内容一样从控制器传递参数/数据(如果尚未通过会话提供)。我将为要使用的视图创建一个实用程序方法,以便逻辑/规则不会在视图中结束。
答案 2 :(得分:1)
我看到你的问题的方式,基于角色的安全性将是要走的路。
如果他们是组织者,那么他们就是组织者角色。但是你需要抽象一点。由于理论上组织者角色理论上是所有其他事件的组织者,因此您需要一种方法来做出此决定并根据请求填充角色,以便用户A是事件A的组织者,但不是事件B的组织者。这理想地需要在访问控制器代码之前发生,因此您的选择是global.asax.cs或auth过滤器。
答案 3 :(得分:0)
Using Roles and custom Role Attributes似乎非常适合(尽管我可以说没有代码或更好地理解您的代码库,没有人可以为您的问题提供“最佳”方式)。