1

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

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

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

4

1 回答 1

1

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

除此之外,每次点击控制器时,都可以查询HttpContext.User实现的属性IPrincipal。此属性具有IsInRole用于与 RoleProvider 通信以获取用户是否在特定组中的信息的方法。

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

角色可以存储在 cookie 中(以缓存它们),或者您可以Application_AuthenticateRequestglobal.asaxGenericPrincipal中实现并手动初始化。这个对象被传递给 HttpContext.User。此对象的构造函数接受使用 IsInRole 方法查询的角色数组。

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

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

更新:如果您需要更高级的选项,其中每个角色都可以具有一个或多个功能,例如“使用搜索”、“可以做某事”、“可以做那件事”,我将实现以下安全逻辑:

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

UsersRoles 表用于将用户添加到特定角色。RolesAccessRights 表是您为每个角色定义特定权限的地方。用户从不与功能性对话。(顺便说一句,此命名约定只是一个示例,您将遵循您的命名约定)。

在我的上一份工作中,这就是我们实现审计系统的方式(它是基于 Web 表单的)。但是,在 MVC 中,您可以覆盖AuthorizationAttribute以检查用户的角色并检查角色是否已定义访问权限。考虑到您有特定的安全要求,您必须在您看到需要和必要性的每个操作上使用此属性。

如果您打算实现此逻辑,请忘记 Membership、MembershipUser 和 Roles。老实说,我不再使用这些类了。我有我自己实现的自定义安全性,并且我在最后 4 个项目中使用了它,无需更新或修改。

更新 2:我们使用的安全解决方案基于自定义 MembershipProvider 和 RoleProvider。现在想一想,依赖它是一个错误,因为必须通过实体框架映射对 AccessLevel 表的访问。因此,我们必须想办法查询我们的安全表。

我对您的建议是完全忽略与成员资格和角色相关的类。第一个原因是,当您覆盖提供程序时,您将避免使用不必要的方法和属性来困扰自己。方法体中的方法太多了throw new NotSupportedException()

建议的实施

您将需要以下表格:

  1. 用户- (您至少需要三列 UserId、UserName、Password)。如果您想对密码进行哈希处理,您可能还必须存储盐。其他列,如 FirstName、LastName 等。我建议您将其存储在不同的表中并将其与 UserId 链接。至于 UserId 类型,是否使用int或由您决定Guid
  2. 角色- (您至少需要两列 RoleId、RoleName)。同样,与 UserId 一样,由您决定要使用哪种数据类型。
  3. UsersRoles - 存储 UserId 和 RoleId。您可能想要存储诸如IsActive角色是否是一个位值等属性。
  4. AccessRights - 这是您存储访问权限密钥的地方。在您的情况下,例如UseSearchEditPostsDeletePosts等。在这里您应该至少使用三列 AccessRightId、AccessRightKey 和 AccessRightDescription。如果您有很多访问权限密钥,此描述字段将变得非常有价值。
  5. RolesAccessRights - 您可以在此处定义已添加特定访问权限的角色。还具有IsActive位值以禁用对角色的特定访问权限。

在 MVC 中,您将覆盖AuthorizationAttribute。在此属性中,您将指定有权访问控制器和/或操作的访问权限列表。您打算如何执行此操作完全取决于您,但我会创建一个枚举,其中包含与 AccessRightsKeys 相同的值列表。这样您就可以使用强类型访问权限而不是基于字符串的列表。有关实现自定义授权属性的更多信息,请查看参考列表。

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

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

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

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

参考:

  1. 实现角色提供者
  2. 角色类
  3. 如何:创建自定义 AuthorizationAttribute
于 2013-03-07T20:03:53.210 回答