MVC 4:传递用户组数据

时间:2013-03-05 14:49:33

标签: asp.net-mvc-4 asp.net-membership

我正在使用ASP.NET重写我的PHP网站并编写会员系统。

我知道我可以扩展MembershipUser来添加特定于成员的属性,但是如何传递布尔组信息,例如使用搜索编辑帖子等非特定于用户的信息?是否有一个我缺少的框架项,或者我应该创建一个超级对象来传递这个和其他设置?

基本上我希望它是一种有效的方式来访问我的控制器中的用户组属性。

1 个答案:

答案 0 :(得分:1)

除了扩展MembershipProvider之外,您还可以扩展RoleProvider。 RoleProvider负责检查用户所属的组,注册新角色,将用户添加到角色等。要使用角色,您将使用包含大量静态方法的Roles类。

除此之外,每次点击Controller时,都可以查询实现HttpContext.User的{​​{1}}属性。此属性具有方法IPrincipal,用于与RoleProvider通信以在用户位于特定组中时获取信息。

此外,为了允许访问控制器或操作,您可以使用IsInRole属性并列出有权访问控制器的特定角色。

可以将角色存储在Cookie中(以缓存它们),也可以在 global.asax 中实施Authorization并手动初始化Application_AuthenticateRequest。该对象被传递给HttpContext.User。此对象的构造函数接受使用IsInRole方法查询的角色数组。

GenericPrincipal

以上代码未经过测试。我是从头脑中写下来的。它应该为您提供一个非常好的图片,如何缓存角色并以最有效的方式使用它们。

更新:如果您需要更多高级选项,其中每个角色都可以拥有一个或多个功能,例如"使用搜索","可以执行某些操作&#34 ;,"可以做到",我将实现以下安全逻辑:

  • 用户
  • 角色(用户属于角色)
  • AccessRight(角色可以拥有一个或多个访问权限。)

UsersRoles表用于将用户添加到特定角色。 您可以在RolesAccessRights表中定义每个角色的特定权限。 用户从不与功能性交谈。 (顺便说一句,这个命名约定只是一个例子,你将遵循你的命名约定。)

在我上一次工作中,这是我们实施审计系统的方式(它是基于Web窗体的)。但是,在MVC中,您可以覆盖protected void Application_AuthenticateRequest(Object sender, EventArgs e) { // Check if user is authenticated if (HttpContext.User != null) { // Extract roles from a cookie if you used FormsAuthentication // or read them from a cookie or from some other cached location // Split roles into array of strings var roles = listOfRoles.ToArray(); // If it is stored in a List<string>. var identity = HttpContext.User.Identity; var principal = new GenericPrincipal(identity, roles); HttpContext.User = principal; } } 以检查用户的角色并检查角色是否已定义访问权限。考虑到您有特定的安全要求,您必须在您认为需要和必要的每个操作上使用此属性。

如果您计划实施此逻辑,请忘记Membership,MembershipUser和Roles。老实说,我不再使用这些课程了。我有我自己的自定义安全性,我在最后4个项目中使用它而不需要更新或修改。

更新2 :我们使用的安全解决方案基于自定义MembershipProvider和RoleProvider。现在考虑一下,依赖它是一个错误,因为访问AccessLevel表必须通过Entity Framework进行映射。因此,我们不得不查询我们的安全表。

我对你的建议是完全忽略与会员和角色相关的课程。第一个原因是,当您覆盖提供程序时,您将避免使用不必要的方法和属性来打扰自己。方法体中的AuthorizationAttribute方法太多了。

建议实施

您需要以下表格:

  1. 用户 - (您需要至少三列UserId,UserName,Password)。如果要对密码进行哈希处理,则可能还需要存储盐。其他列如FirstName,LastName等。我建议您存储在不同的表中并将其与UserId链接。对于UserId类型,您可以使用throw new NotSupportedException()还是int
  2. 角色 - (您至少需要两列RoleId,RoleName)。同样,与UserId一样,由您决定使用哪种数据类型。
  3. UsersRoles - 存储UserId和RoleId。您可能希望存储属性,例如角色 IsActive 是否为位值。
  4. AccessRights - 您可以在此处存储访问权限的密钥。在您的情况下,就像 UseSearch EditPosts DeletePosts 等。在这里,您应该使用至少三列AccessRightId,AccessRightKey和AccessRightDescription。如果你有很多访问权限密钥,这个描述字段将变得非常有价值。
  5. RolesAccessRights - 您可以在此处定义添加了特定访问权限的角色。还具有 IsActive 位值,以禁用对角色的特定访问权限。
  6. 在MVC中,您将覆盖 AuthorizationAttribute 。在此属性中,您将指定有权访问控制器和/或操作的访问权限列表。你打算如何做到这完全取决于你,但我会创建一个枚举,其中包含一个与AccessRightsKeys相同的值列表。这样,您可以使用强类型访问权限而不是基于字符串的列表。有关实现自定义授权属性的更多信息,请查看引用列表。

    在此属性的内部,您将读取用户ID并检索角色。比较您为角色(RolesAccessRights表)指定的AccessRightsKeys,以查看角色是否具有访问权限以及规则是否处于活动状态。

    对于基于解决方案的实现,我将实现安全服务层,该层与基于安全性的存储库和工作单元解决方案进行通信。因为您使用的是MySQL,所以我不知道您可以使用哪种ORM,或者您是否必须依赖ADO.NET和MySQL的OLEDB提供程序。

    我通常采用的是自上而下的方法。我从高处(如表示层)实现并向下走向数据访问层。最后,我只有那些我真正使用的方法,而且没有冗余。

    嗯,我希望这会给你一些关于如何做到这一点的图片。至于时间,你可以在大约8-10小时内完成。

    参考:

    1. Implementing a Role Provider
    2. Roles Class
    3. How to: Create a Custom AuthorizationAttribute