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

发布于 2024-08-07 01:57:43 字数 622 浏览 2 评论 0 原文

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

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

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

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

  4. 如果我有一个网站,人们可以在其中创建群组并成为其群组的管理员,并且这些管理员可以向群组中的人员授予不同的管理权限组合(例如,扎克创建了一个名为 Mountain 的群组,并授予一名成员我应该如何在 MySQL 中使用一个列来说明他们是哪个组的管理员以及什么组。他们有什么能力?例如列:删除、批准、GroupMemberOf、GroupAdminOf 和使用检查。

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

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

I am going to be making a small user system but I have questions.

  1. If I were to make a registration table (mysql), what is wrong with just storing the password and username into the database without encryption?

  2. I am trying to think of how to build the admin portion. Should I just check a column in the database to see if user is admin or not? If true, then admin page will be revealed. 

  3. For admin powers, let's say I have 3 powers: delete user, approve user, and move user. In a few scenarios, I may want to give some people only the ability to approve, or delete, or all, or any combination. How would I make this? I was thinking of having a column for each power and have the script check each column. Let's assume I have over 20 powers that will be added.

  4. If I have a website where people can create groups and become admins of their groups and the these admins can give different combination of admin powers to people in their group (For ex, Zack creates and group called Mountain and grants one member the ability approve new group members and grants a second member the ability to delete members and assigns a third member the ability to delete and approve. How will I structure this in MySQL? Should I use a columns that say what group are they admin of and what ability do they have? E.g. columns: Delete, Approve, GroupMemberOf, GroupAdminOf and use checks.

I have an idea but I want to learn the more sophisticated ways.

Thanks for the answers so far, however, I am really looking for ideas on a structure ( Question 2 - 4 ). Please let me know if I can help clear up the question.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

醉殇 2024-08-14 01:57:43
  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());
    }
}

[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. Hash user passwords with unique salts for each users, so that when your database can be accessed by an outsider, they cannot decrypt the passwords, and the salt mitigates rainbow table attacks.

2 - 4. Use a table for access levels (1: member, 2: moderator (approval), 3: admin), and use yet another different table for user permissions where you store many-to-many connections like this:

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

In your case, user 1 is admin for the whole site, user 2 is admin for group 3 and moderator for group 2, user 3 is member of group 2.

[EDIT:]

Some more thoughts on restricting powers for the different roles: Depending on your setup you should use some role enforcement on a per-page basis, e.g. in an MVC framework, I would extend the base controller to require a (role) authorization function that has to be called for each method, otherwise it should throw an exception. Methods (pages) that do not require the user to log in can use a dummy authorization.

So the authorization class will look like

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
}

Your new base controller class will look like this:

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

And finally in the end your controllers will look like:

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:]

If you are not familiar with OOP, then you can do the following:

Here is a sample layout for a roles table:

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

You can then make a function authorize() to include in all your files:

// 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

}

In your files include this function and do the following

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 
心奴独伤 2024-08-14 01:57:43
  1. 如果您存储的密码没有加密,那么当有人设法窃取您的数据库或获得对其的读取访问权限时,您将泄露所有客户的密码。遗憾的是,大多数人在站点之间重复使用用户名和密码,因此如果不保护用户的密码,就会对用户造成很大的伤害。 (也许他们应该更清楚,但大多数人不知道。)
  1. If you store passwords without encryption, you will be revealing all of your customer's passwords when someone manages to steal your database, or get read access to it. Sadly, most people reuse usernames and passwords between sites, so you are doing your users a big disfavor by not protecting their passwords. (Maybe they should know better, but most don't.)
素手挽清风 2024-08-14 01:57:43

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

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

1) Storing clear text passwords means that if anyone does get access to your database, they still won't know the password. The hype around salting and encryption passwords is quite silly, a simple method will do just fine for anyone.

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

What this does is encrypts a password through md5();, You can't get the password back after you encrypt it with md5(). Salting it also ensures that there's no way to just find the password.

If you want to compare and see if the password works, just md5 the input the exact same way like below:

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

2) That question depends on how you want to integrate groups with the admin side of things. If there's no other permissions setup at all, it's safe to just store a single field in the database with the account level. Otherwise, use my next point to find out if they are an admin or not.

3) The simplest way to implement a permissions system is like this, there are other ways but it's best not to complicate it. If you wanted permissions for each group you could add an additional column like prm_group_id and find out each user in a particular group's permission. But anyway, here's how it works:

Create a table to hold the permissions

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

Each row holds a flag or permission.
Then it's quite simple to find out if they have the required permission through a bit of SQL and 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;
}

This allows you to add and delete permissions quite easily, and to check and see if they have a permission. Only downside is managing permissions can get abit tricky.

我的奇迹 2024-08-14 01:57:43

对于第 2-4 点,您可能需要查看基于角色的访问控制

For points 2-4, you might want to look at Role-Based Access Control.

诗化ㄋ丶相逢 2024-08-14 01:57:43

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

1 - I would suggest you encrypt your passwords using a unique salt for each user. That way if your system is ever compromized, your users' passwords won't be available to the hackers (without more hacking on their part)

http://phpsec.org/articles/2005/password-hashing.html (a little old, but has some good info)

2, 3, 4 - All of this is possible with a wide array of web languages. I would suggest first reading up on database design and figuring out what sort of normalization and table schema would be ideal for your situation. If you decide to add more powers to the admin users in the future, you can design for that from the beginning and avoid any headaches in the future and still be within your current requirements.

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

小情绪 2024-08-14 01:57:43
  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

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

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

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

if( $permbit === "approve" )

vs

if( $permbit === 1 )

祝你好运!

  1. Obviously the suggested is to store it hashed, but there's benefits to not doing so as well. It really comes down to what you need.

2+.
I threw together a little sql schema for this here

Basically, store the users, the groups, and the permbits you need in the separate tables. Then, associate users to groups, and permissions to the users in the groups. To give a person "all" you simply make sure that your programming logic (either PHP or MySQL stored proceedure) gives the new user all of the available permissions in the permissions table. To accomplish this in MySQL you could perform a query like this:

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

This will insert all possible permissions into the group_user_permission table for the groupid and userid given (in this case groupid 1 and userid 1).

Now, where ever you need to check permissions you can run a very simple query against the group_user_permission table to see if that user, in that group, has permission to do whatever it is they are trying to do. This is ultimately flexible because you won't have to alter tables if you need to rename permbits, add permbits, or remove permbits.

Additionally, because of the use of string keys in the permission table, you can use those values in a textual format that will make sense when reading them (vs using autoincrementing numbers). Making your PHP checks look like this:

if( $permbit === "approve" )

vs

if( $permbit === 1 )

Good luck!

白云不回头 2024-08-14 01:57:43

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

user-permissions-and-cakephp

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

PermID | Deny or Allow | Action | Entity

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

拒绝或允许意味着您可以创建 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 和 1。仅 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。

抱歉,如果这有点糟糕,但我希望你能明白它的要点。 (如果之前的答案谈到了这一点,我深表歉意,因为我认为我没有读完……)

I'm a little late to the game for this, but you might like to take a look at how CakePHP does its authorization. (If you're using PHP you might find that using the CakePHP framework gives you some of this control without having to code it.)

user-permissions-and-cakephp

Also, I've found it useful to just keep a list of actions (such as CRUD or Admin) against entities, so you'd apart from the normal user/password table you'd have a table with the fields as below.

PermID | Deny or Allow | Action | Entity

You then have another table that maps groups to PermId and another that maps users & groups (recursively if necessary) into groups (as people have already talked about).

The Deny or Allow means that you can create ACLs to allow use or DACLs to deny use if the default is to allow an action (which probably isn't the best idea normally), or if there is a smaller group that has to be denied access within a larger one. You'd generally check first to see if there was an explicit Deny on an action against an entity for a group/user.

So you might have something like:

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

So, as an illustration, an admin group would map to entries 1-5, a "normal user" group might map to 1 & 5 only. (For group, read "person" or "user" if you want).

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

Obviously this is easily extensible as when a new action or entity (e.g. directory) arises in the system it's just a case of adding the appropriate entries into the tables without the need to change schema. You can use actions of "All", for example, and use a DACL for a particular exclusion. Here's a Power User that can do everything but delete a 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

In your case I'd imagine that the Entities could incorporate the group name, or some token that would mean "your home group" or something e.g. {homegrp}/UserEntry, rather than just UserEntry which a sysadmin might have.

Sorry if that was a bit woffley but I hope you get the gist of it. (Apologies if any previous answer talked about this as I don't think I read all the way through...)

罗罗贝儿 2024-08-14 01:57:43

2.. 是的

3.. 如果您的权限数量有限,那就很简单了 4

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

2.. Yes

3.. That is simple if you have a finite number of permissions

4.. I wrote this a couple of years ago, and it's in heavy use at a large company. Contact me if you want more info on the schema.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文