在简单的CMS上工作 - 如何处理用户拥有的访问权限? [关闭]

I'm working on a personal CMS and I've got a problem. I wanted to define access levels such as CAN_DELETE_THREAD, CAN_EDIT_MESSAGE or CAN_CREATE_THREAD as binary flags, but I don't know how a function 'has_flag' would work. For example, if I took a user from the db and wanted to check if he can edit messages, how would I go around doing that?

Thanks!

You could create a permissions database table, and a permissions_users table that joins permissions to users, and then check on a per-page basis if the logged-in user can view that page.

Imagine you have a User model, and a permission with an ID of 1:

if ($user->hasPermission(1)) {
    // show form or whatever
}
else {
    throw new ForbiddenException();
}

Your hasPermission() method could be as simple as:

<?php
class User extends Model {

    public function hasPermission($permission_id) {
        $sql = "SELECT COUNT(*) FROM `permissions_users` WHERE `user_id` = :user_id AND `permission_id` = :permission_id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->bindParam(':user_id', $this->id, PDO::PARAM_INT);
        $stmt->bindParam(':permission_id', $permission_id, PDO::PARAM_INT);
        return ($this->pdo->fetchColumn() > 0); // returns true if at least 1 result
    }
}

Obviously you'll need to adjust this to fit your application.

Do you need per-user or per-role access settings?

per-role would be way more scalable, especially if your system will be open for many users.

At first, I'd define actions that a user can do, grouped by some category ("Thread" with [Add, Edit, Delete, Flag, Archive, Whatever]), then you could create a list to define for each role and each action if it is allowed or denied.

You could decrease the amount of needed specifications in that table if you define a default value (everything is allowed if not denied or vice versa).

A bit more details would be needed for further help ;)

You can do that in several ways. You might store an integer property associated with the user, then define the flags as integer powers of 2:

define('CAN_CREATE_THREAD', 0x0010);
define('CAN_DELETE_THREAD', 0x0020);

then to your hasFlag($flag) could be something like

return ($this->BinaryFlags & $flag);

Otherwise you can store all the flags in the database:

CREATE TABLE flags
(
    id integer not null primary key auto_increment,
    name varchar(32)
);

CREATE TABLE has_flag
(
    user_id integer,
    flag_id integer
);

and your hasFlag function is a query to the database.

Role-level access is the same, except that you do not store flags associating them to an user, but rather associate an user to a role (so you have a table like (user_id, role_id) ), and then associate the flags to the role as shown above.

The advantage is that you can define a person as "Section XYZ Administrator" without having to remember and set all permissions one by one; the disadvantage is that you can't have intermediate states (say, a semi-administrator that can edit but not create) unless you create the role first.