Как структурировать группы на сайте? (администратор, полномочия администратора, личность пользователя) - PullRequest
3 голосов
/ 06 октября 2009

Я собираюсь создать небольшую пользовательскую систему, но у меня есть вопросы.

  1. Если бы я должен был создать таблицу регистрации (mysql), что плохого в том, чтобы просто сохранить пароль и имя пользователя в базе данных без шифрования?

  2. Я пытаюсь придумать, как создать административную часть. Должен ли я просто проверить столбец в базе данных, чтобы увидеть, является ли пользователь администратором или нет? Если это правда, то страница администратора будет показана.

  3. Для полномочий администратора, скажем, у меня есть 3 полномочия: удалить пользователя, утвердить пользователя и переместить пользователя. В некоторых сценариях я могу захотеть дать некоторым людям только возможность одобрить, или удалить, или все, или любую комбинацию. Как бы я это сделал? Я думал о наличии столбца для каждой степени и чтобы скрипт проверял каждый столбец. Давайте предположим, что у меня есть более 20 сил, которые будут добавлены.

  4. Если у меня есть веб-сайт, на котором люди могут создавать группы и становиться администраторами своих групп, и эти администраторы могут предоставлять различные комбинации полномочий администратора людям в своей группе (например, Зак создает группу под названием «Гора и гранты»). один участник может утверждать новых членов группы, а второй дает возможность удалять участников и назначает третьему члену возможность удалять и утверждать. Как я буду структурировать это в MySQL? Должен ли я использовать столбцы, в которых указано, какие группы они администраторы? и какие возможности они имеют? Например, столбцы: Удалить, Одобрить, GroupMemberOf, GroupAdminOf и использовать проверки.

У меня есть идея, но я хочу изучить более сложные способы.

Спасибо за ответы, однако, я действительно ищу идеи относительно конструкции (Вопрос 2-4). Пожалуйста, дайте мне знать, если я могу помочь прояснить вопрос.

Ответы [ 8 ]

5 голосов
/ 02 ноября 2009
  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.

[EDIT:]

Еще несколько мыслей об ограничении полномочий для разных ролей: в зависимости от вашей настройки вы должны использовать некоторое усиление ролей для каждой страницы, например, в среде 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:]

Если вы не знакомы с ООП, то вы можете сделать следующее:

Вот пример макета таблицы ролей:

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 
3 голосов
/ 03 ноября 2009

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

Это позволяет довольно легко добавлять и удалять разрешения, а также проверять и видеть, есть ли у них разрешение. Только недостатком является то, что управление разрешениями может стать хитрым.

3 голосов
/ 06 октября 2009
  1. Если вы храните пароли без шифрования, вы будете раскрывать все пароли вашего клиента, когда кому-то удастся украсть вашу базу данных или получить к ней доступ для чтения. К сожалению, большинство людей повторно используют имена пользователей и пароли между сайтами, поэтому вы наносите большой вред своим пользователям, не защищая их пароли. (Может быть, они должны знать лучше, но большинство не знают.)
0 голосов
/ 03 ноября 2009

Для пунктов 2-4 вы можете посмотреть Контроль доступа на основе ролей .

0 голосов
/ 03 ноября 2009

Я немного опоздал с игрой для этого, но вы могли бы взглянуть на то, как CakePHP выполняет свою авторизацию. (Если вы используете PHP, вы можете обнаружить, что использование инфраструктуры CakePHP дает вам часть этого элемента управления без необходимости его кодирования.)

пользовательские разрешения-и-CakePHP

Кроме того, я считаю полезным хранить список действий (например, CRUD или Admin) для сущностей, чтобы вы, кроме обычной таблицы «пользователь / пароль», имели бы таблицу с полями в виде ниже.

PermID | Deny or Allow | Action | Entity

Затем у вас есть другая таблица, которая отображает группы в 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 и 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, который может иметь системный администратор.

Извините, если это было немного глупо, но я надеюсь, что вы поняли суть этого. (Извиняюсь, если в каком-либо предыдущем ответе говорилось об этом, так как я не думаю, что прочитал все до конца ...)

0 голосов
/ 03 ноября 2009
  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 1 и идентификатор пользователя 1).

Теперь, когда вам когда-нибудь понадобится проверить разрешения, вы можете выполнить очень простой запрос к таблице group_user_permission, чтобы узнать, имеет ли этот пользователь в этой группе разрешение делать то, что он пытается сделать. Это в конечном итоге гибко, потому что вам не придется изменять таблицы, если вам нужно переименовать разрешения, добавить разрешения или удалить разрешения.

Кроме того, из-за использования строковых ключей в таблице разрешений вы можете использовать эти значения в текстовом формате, который будет иметь смысл при их чтении (вместо использования автоинкрементных чисел). Чтобы ваши проверки PHP выглядели так:

if( $permbit === "approve" )

против

if( $permbit === 1 )

Удачи!

0 голосов
/ 11 октября 2009

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

0 голосов
/ 06 октября 2009

2 .. Да

3 .. Это просто, если у вас есть конечное число разрешений

4 .. Я написал это пару лет назад, и он широко используется в большой компании. Свяжитесь со мной, если вы хотите больше информации о схеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...