3

我将制作一个小型用户系统,但我有问题。

  1. 如果我要制作一个注册表(mysql),那么只将密码和用户名存储到数据库中而不加密有什么问题?

  2. 我正在考虑如何构建管理部分。我是否应该只检查数据库中的一列以查看用户是否为管理员?如果为真,则将显示管理页面。 

  3. 对于管理员权限,假设我有 3 个权限:删除用户、批准用户和移动用户。在少数情况下,我可能只想给某些人批准、删除、全部或任何组合的能力。我该怎么做?我正在考虑为每个电源设置一列,并让脚本检查每一列。假设我有 20 多个要添加的权力。

  4. 如果我有一个网站,人们可以在其中创建群组并成为其群组的管理员,并且这些管理员可以为其群组中的人员提供不同的管理权限组合(例如,Zack 创建名为 Mountain 的群组并授予一名成员批准新组成员并授予第二个成员删除成员的能力并分配第三个成员删除和批准的能力。我将如何在 MySQL 中构建这个?我应该使用一个列来说明他们管理哪个组以及他们有什么能力有吗?例如列:Delete、Approve、GroupMemberOf、GroupAdminOf 和使用检查。

我有一个想法,但我想学习更复杂的方法。

感谢到目前为止的答案,但是,我真的在寻找关于结构的想法(问题 2 - 4)。如果我能帮助解决这个问题,请告诉我。

4

8 回答 8

5
  1. 为每个用户使用唯一的盐对用户密码进行哈希处理,这样当您的数据库可以被外人访问时,他们无法解密密码,并且盐可以缓解彩虹表攻击

2 - 4. 使用一个表来表示访问级别(1:成员,2:主持人(批准),3:管理员),并使用另一个不同的表来存储多对多连接的用户权限,如下所示:

id (auto_increment)|usr_id|role_id|group_id
-------------------------------------------
1                  |1     |3      |-1
2                  |2     |2      |1
3                  |2     |3      |2
4                  |3     |1      |2

在您的情况下,用户 1 是整个站点的管理员,用户 2 是组 3 的管理员和组 2 的版主,用户 3 是组 2 的成员。

[编辑:]

关于限制不同角色的权力的更多想法:根据您的设置,您应该在每页的基础上使用一些角色强制执行,例如在 MVC 框架中,我将扩展基本控制器以要求具有的(角色)授权功能为每个方法调用,否则应该抛出异常。不需要用户登录的方法(页面)可以使用虚拟授权。

所以授权类看起来像

class Authorization
{
    public $authorized = false;

    public function dummy()
    {
        $this->authorized = true;
    }

    public function member($usr_id, $group_id = null)
    {
        $sql = "SELECT usr_id FROM usr_roles WHERE usr_id = " . $usr_id . ($group_id !== null) ? " AND group_id " . $group_id : "";
        // count the results of $sql query
        // or some more stuff
        if ($results > 1)
        {
            $this->authorized = true;
        }
        else
        {
            $this->authorized = false;
        } 
    }

    // the other functions
}

您的新基控制器类将如下所示:

class BaseController extends Controller
{
    protected $authorization;
    public function __construct()
    {
        $this->authorization = new Authorization();
    }

    public function render()
    {
        if ($this->authorization->authorized === true)
        {
            parent::render
        }
        else
        {
            // redirect to not authorized page 
        }
    }
}

最后,您的控制器将如下所示:

class IndexController extends BaseController
{
    // some stuff, methods etc.

    // methods needs logged in user and user must be a member. 
    public function index()
    {
        $this->authorization->member($session_user->getId());
    }
}

[编辑2:]

如果您不熟悉 OOP,则可以执行以下操作:

这是角色表的示例布局:

role_id|role_name
-----------------
1      |member
2      |moderator
3      |admin

然后,您可以创建一个函数 authorize() 以包含在您的所有文件中:

// role_name = "member", "moderator", "admin"
function authorize($usr_id = null, $role_name = null, group_id = null)
{
    // test for user in group and role, return boolean

}

在您的文件中包含此功能并执行以下操作

if (authorize($usr_id, "moderator", 2)
{
    // show stuff, if user with $usr_id is moderator for group 2
}
else
{
    // do something else
}
// stuff for all 
于 2009-11-02T15:51:17.077 回答
3
  1. 如果您在未加密的情况下存储密码,那么当有人设法窃取您的数据库或获得对它的读取权限时,您将泄露所有客户的密码。可悲的是,大多数人在站点之间重复使用用户名和密码,因此您不保护他们的密码是对用户的极大不利。(也许他们应该知道得更多,但大多数人不知道。)
于 2009-10-06T18:00:27.950 回答
3

1)存储明文密码意味着如果有人确实可以访问您的数据库,他们仍然不会知道密码。围绕加盐和加密密码的炒作非常愚蠢,一个简单的方法对任何人都可以。

$password = "Mypassword";
$salt = "a unique and constant string";
$password = md5($password.$salt);

这样做是通过 加密密码md5();,使用 md5() 加密后无法取回密码。加盐还可以确保无法找到密码。

如果您想比较并查看密码是否有效,只需 md5 输入完全相同的方式,如下所示:

$password = "check_this_password";
if(md5($password.$salt) === $originalPassword) 
{ 
    //same password
}

2)这个问题取决于您希望如何将组与管理方面集成在一起。如果根本没有其他权限设置,只需将单个字段存储在具有帐户级别的数据库中是安全的。否则,请使用我的下一点来确定他们是否是管理员。

3)实现权限系统的最简单方法是这样,还有其他方法,但最好不要复杂化。如果您想要每个组的权限,您可以添加一个额外的列,例如prm_group_id并找出特定组权限中的每个用户。但无论如何,这是它的工作原理:

创建一个表来保存权限

prm_user_id  | prm_permission
   0         | Admin
   0         | Delete
   1         | Add

每行都有一个标志或权限。然后通过一些 SQL 和 PHP 就很容易确定他们是否具有所需的权限。

function hasPermission($permission, $userID)
{
  $permissions = array();

  $sql = "SELECT prm_permission FROM user_permissions WHERE prm_user_id = $userID";
  $query = mysql_query($sql);

  while($data = mysql_fetch_array($query))
  {
     $permissions[] = $data['prm_permission'];
  }

  //Check if they have a permission with this:
  if(in_array($permission, $permissions))
  {
     return true;
  }
return false;
}

这使您可以很容易地添加和删除权限,并检查他们是否有权限。唯一的缺点是管理权限可能会变得有点棘手。

于 2009-11-02T23:58:55.193 回答
1

对于第 2-4 点,您可能需要查看Role-Based Access Control

于 2009-11-03T11:46:30.760 回答
0

1 - 我建议您为每个用户使用唯一的盐来加密您的密码。这样,如果您的系统遭到入侵,黑客将无法使用您的用户密码(无需他们进行更多黑客攻击)

http://phpsec.org/articles/2005/password-hashing.html(有点旧,但有一些很好的信息)

2, 3, 4 - 所有这些都可以通过多种网络语言实现。我建议首先阅读数据库设计并确定哪种规范化和表模式最适合您的情况。如果您决定将来为管理员用户添加更多权限,您可以从一开始就进行设计,避免将来出现任何麻烦,并且仍然符合您当前的要求。

http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html http://www.peachpit.com/articles/article.aspx?p=30885

于 2009-10-11T18:26:09.727 回答
0
  1. 显然,建议将其存储为散列,但不这样做也有好处。它真的归结为你需要什么。

2+。我在这里拼凑了一个小 sql 模式

基本上,将所需的用户、组和许可存储在单独的表中。然后,将用户关联到组,并将权限关联到组中的用户。要给一个人“全部”,您只需确保您的编程逻辑(PHP 或 MySQL 存储过程)为新用户提供权限表中的所有可用权限。要在 MySQL 中完成此操作,您可以执行如下查询:

INSERT INTO group_user_permissions
    SELECT `group_user`.`groupid`, `group_user`.`userid`, `permission`.`permbit`
        FROM permission, `group_user`
    WHERE `group_user`.`groupid` = 1
        AND `group_user`.`userid` = 1

这会将所有可能的权限插入到 group_user_permission 表中,用于给定的 groupid 和 userid(在本例中为 groupid 1 和 userid 1)。

现在,无论何时您需要检查权限,您都可以对 group_user_permission 表运行一个非常简单的查询,以查看该组中的该用户是否有权执行他们尝试执行的任何操作。这最终是灵活的,因为如果您需要重命名许可、添加许可或删除许可,您将不必更改表。

此外,由于在权限表中使用了字符串键,您可以以文本格式使用这些值,这在阅读它们时是有意义的(与使用自动递增数字相比)。使您的 PHP 检查看起来像这样:

if( $permbit === "approve" )

对比

if( $permbit === 1 )

祝你好运!

于 2009-11-03T00:35:02.203 回答
0

我对此有点晚了,但是您可能想看看 CakePHP 如何进行授权。(如果您使用 PHP,您可能会发现使用 CakePHP 框架可以为您提供一些控制,而无需编写代码。)

用户权限和 cakephp

此外,我发现只保留针对实体的操作列表(例如 CRUD 或 Admin)很有用,因此除了普通的用户/密码表之外,您还有一个包含以下字段的表。

许可ID | 拒绝或允许 | 行动 | 实体

然后,您有另一个表将组映射到 PermId,另一个表将用户和组(必要时递归)映射到组(正如人们已经讨论过的那样)。

Deny 或 Allow 意味着您可以创建 ACL 以允许使用或 DACL 拒绝使用,如果默认是允许操作(通常这可能不是最好的主意),或者如果有一个较小的组必须被拒绝访问更大的一个。您通常首先检查是否存在针对组/用户的实体的操作的明确拒绝。

所以你可能有类似的东西:

许可ID | 类型 | 行动 | 实体
-------+-------+---------+------------
  1 | 允许 | 阅读 | User_Entry
  2 | 允许 | 删除 | User_Entry
  3 | 允许 | 移动 | User_Entry
  4 | 允许 | 批准 | User_Entry
  5 | 允许 | 创建 | User_Entry

因此,作为说明,管理员组将映射到条目 1-5,“普通用户”组可能仅映射到 1 和 5。(对于组,如果需要,请阅读“人”或“用户”)。

身份证 | 组 | PermId
---+--------+-----
 1 | 管理员 | 1
 2 | 管理员 | 2
 3 | 管理员 | 3
 4 | 管理员 | 4
 5 | 管理员 | 5
 6 | 正常 | 1
 7 | 正常 | 5

显然,这很容易扩展,因为当系统中出现新的操作或实体(例如目录)时,只需将适当的条目添加到表中而无需更改架构。例如,您可以使用“全部”操作,并将 DACL 用于特定排除。这是一个高级用户,除了删除 User_Entry 之外,它可以做任何事情。

许可ID | 类型 | 行动 | 实体
-------+-------+---------+------------
  6 | 允许 | 全部 | User_Entry
  7 | 拒绝 | 删除 | User_Entry


身份证 | 组 | PermId
---+--------+-----
 8 | 电源 | 6
 9 | 电源 | 7

在您的情况下,我想实体可以包含组名,或者一些表示“您的家庭组”的令牌或诸如 {homegrp}/UserEntry 之类的东西,而不仅仅是系统管理员可能拥有的 UserEntry。

对不起,如果这有点笨拙,但我希望你能明白它的要点。(抱歉,如果任何先前的答案谈到了这一点,因为我认为我没有通读一遍......)

于 2009-11-03T01:58:56.887 回答
-1

2..是的

3.. 如果您拥有有限数量的权限,这很简单

4.. 这是我几年前写的,它在一家大公司被大量使用。如果您想了解有关架构的更多信息,请与我联系。

于 2009-10-06T18:07:32.837 回答