如何在网站中构建群组? (管理员,管理员权限,用户身份)

时间:2009-10-06 17:49:02

标签: php mysql admin administration mysql-management

我将建立一个小型用户系统,但我有疑问。

  1. 如果我要创建一个注册表(mysql),只是将密码和用户名存储到数据库中而没有加密会出现什么问题?

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

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

  4. 如果我有一个人们可以创建群组并成为群组管理员的网站,这些管理员可以为群组中的人提供不同的管理权限组合(例如,Zack创建和群组称为Mountain和奖励一个成员能够批准新的组成员,并授予第二个成员删除成员的能力,并授予第三个成员删除和批准的能力。我将如何在MySQL中构建这个?我应该使用列来说明他们管理的是哪个组他们有什么能力?例如:删除,批准,GroupMemberOf,GroupAdminOf并使用支票。

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

    到目前为止,感谢您的答案,我真的在寻找结构上的想法(问题2 - 4)。如果我能帮忙解决问题,请告诉我。

8 个答案:

答案 0 :(得分:5)

  1. 为每个用户散列具有唯一salt的用户密码,以便当局外人可以访问您的数据库时,他们无法解密密码,并且盐可以缓解rainbow table attacks
  2. 2 - 4.使用表格访问级别(1:成员,2:主持人(审批),3:admin),并使用另一个不同的表来存储用户权限,您可以在此存储多对多连接,如下所示:

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

    <强> [EDIT2:]

    如果您不熟悉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 
    

答案 1 :(得分:3)

  1. 如果您在没有加密的情况下存储密码,当有人设法窃取您的数据库或获取对该数据库的读取权限时,您将泄露所有客户的密码。遗憾的是,大多数人在站点之间重复使用用户名和密码,因此您不会保护自己的密码,从而使您的用户大为不满。 (也许他们应该知道更好,但大多数人都不知道。)

答案 2 :(得分:3)

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

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

这样做是通过md5();加密密码,使用md5()加密后无法获取密码。 Salting它也确保无法找到密码。

如果你想比较并查看密码是否有效,只需输入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;
}

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

答案 3 :(得分: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

答案 4 :(得分:0)

  1. 显然建议将其存储为哈希值,但不这样做也有好处。这真的取决于你的需求。
  2. 2+。 我为这个here

    汇总了一个小的sql架构

    基本上,将您需要的用户,组和permbits存储在单独的表中。然后,将用户关联到组,并将权限关联到组中的用户。为了给所有人“全部”,您只需确保您的编程逻辑(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
    

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

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

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

    if( $permbit === "approve" )
    

    VS

    if( $permbit === 1 )
    
    祝你好运!

答案 5 :(得分:0)

我为此比赛迟到了,但你可能想看看CakePHP如何授权。 (如果您正在使用PHP,您可能会发现使用CakePHP框架可以为您提供一些控制,而无需对其进行编码。)

user-permissions-and-cakephp

另外,我发现只保留一个针对实体的操作列表(例如CRUD或Admin)很有用,所以除了普通的用户/密码表之外你还有一个表格,其中的字段为下方。

PermID | Deny or Allow | Action | Entity

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

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

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

PermID | Type  | Action  | Entity
-------+-------+---------+------------
  1    | Allow | Read    | User_Entry
  2    | Allow | Delete  | User_Entry
  3    | Allow | Move    | User_Entry
  4    | Allow | Approve | User_Entry
  5    | Allow | Create  | User_Entry

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

Id | Grp    | PermId
---+--------+-----
 1 | Admin  | 1
 2 | Admin  | 2
 3 | Admin  | 3
 4 | Admin  | 4
 5 | Admin  | 5
 6 | Normal | 1
 7 | Normal | 5

显然,这很容易扩展,因为当系统中出现新的动作或实体(例如目录)时,只需将相应的条目添加到表中而无需更改模式。例如,您可以使用“全部”操作,并使用DACL进行特定排除。这是一个高级用户,除了删除User_Entry外,可以执行所有操作。

PermID | Type  | Action  | Entity
-------+-------+---------+------------
  6    | Allow | All     | User_Entry
  7    | Deny  | Delete  | User_Entry


Id | Grp    | PermId
---+--------+-----
 8 | Power  | 6
 9 | Power  | 7

在你的情况下,我想象实体可以合并组名,或者某些意味着“你的家庭组”的标记或者例如{homegrp} / UserEntry,而不仅仅是系统管理员可能拥有的UserEntry。

对不起,如果那有点woffley但我希望你得到它的要点。 (如果有任何先前的回答谈到这一点,请道歉,因为我认为我不会一直读到......)

答案 6 :(得分:0)

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

答案 7 :(得分:-1)

2 ..是

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

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