Users

Материал из Smart Core Wiki

Перейти к: навигация, поиск

ВНИМАНИЕ! информация на этой странице может быть не актуальной.

Содержание

Работа с пользователями

Особенности:

  1. Работа в мультисайтовом режиме. Здесь есть такая особенность: предположим используется удалённая база юзеров, а разные проекты на других серверах используют её для аутентификации, регистрации и т.д. В таком случае каждый проект имеет собственные настройки ролей для каждого юзера. В тоже время проект может быть мультисайтовым т.е. в зависимости от домена использовать разные настройки и вот в этом случае один и тотже юзер может считаться зареганым в системе, а может и нет. Т.е. на стороне проекта, будет некая «локальная БД аккаунтов» в которой будет копия юзеров из основной БД.
  2. Использование нескольких провайдеров (в прицнипе эта задача очень сложная и не обязательная на данный момент, можно будет реализовать её только в самой простой форме):
    1. Юзеры будет искаться в каждом заданном провайдере по очереди.
    2. При регистрации юзеры будут добавляться также в провайдер по списку т.е. если первый провайдер вернул отрицательный ответ при регистрации, то система будет пытаться зарегать юзера в следующий. Но тут встаёт вопрос с уникальностью данных т.е. видимо методу регистрации надо будет опрашивать все провайделы на предмет уникальности логина и е-майла и только потом добавлять нового юзера. Также неясно как согласовывать ID юзеров.
  3. При регистрации юзеров, до подтверждения юзера по е-маил, он будет складываться в отдельную таблицу таким образом в основной БД будут только подтверждённые юзеры и как следствие не будет совсем безконтрольного накручивания ID. В этом случае для проверки уникальности данных надо будет проверять как базу с активировнаными юзерами, так и с ожидающими активацию. Разумеется записи в ожидающих активацию будут удаляться через какое-то время, если они небыли подтверждены например 24 часа.
  4. Профиль юзера — это дополнительные данные, которые могут юзаться на разных проектах в дополнение к основным данным учетной записи. Например: хобби, цвет глаз и т.д.
  5. Аутентифицироваться можно разными способами: парой логин/пароль, facebook, vk, twitter, openID, OAuth и т.д....

Система будет представлена следующими основными компонентами:

  1. Authentication — Система распознование пользователя.
  2. AccountsProvider — База учетных записей пользователей
  3. Authorization — Наделение правами аутентифицированного юзера.
  4. Profile — Профили юзеров.

Притом, аутнетификация будет использовать аккаунт провайдер, а вот утентификация не обязательна.

База учетных записей

SmartCore\Component\AccountsProviders\Base;

Для компонента аутентификации предоставляется 2 метода:

  1. authenticateByLogin($login, $password = null, $period = 0) — аутентироваться по логину.
  2. authenticateByToken($token) — аутентироваться по токену.

Публичные методы:

  1. createAccount
  2. createLogin
  3. deleteAccount
  4. deleteLogin
  5. getProperties
  6. updateProperties
  7. createProperty
  8. deleteProperty
  9. updatePassword
  10. findByProperty
  11. touch($login, $password = null) — проверить cуществует ли такой логин.

Провайдеры

Источники учетных записей.

  1. Array — Хранение аккаунтов в РНР массиве (в Symfony 2 известен как «Memory»). Пригодно для небольшого кол-ва учетных записей. В этом провайдере невозможно внесение изменений методами create, delete, update.
  2. FlatFile — Структура основанная на простых текстовых папках и файлах.
  3. Remote — Удалённый сервис.
  4. Database — SQL СУБД.

Аутентификация

SmartCore\Component\Authentication\User;

Основные методы:

  1. login($login, $password = null, $period = 0) — $password не обязателен. period — на сколько запомнить юзера, в случае если способ аутентификации куки - то устанавливается время жизни куки т.е. может быть месяц, год т.д. а если только сессии, то надо устанавливать срок жизни сесиии, но тут надо отслеживать некий реальный срок, например не больше 15 минут..
  2. logout() — выход. если режим сессии, то уничтожается сессия, а если куки, то уничтожается сессия, а также токен в куке.
  3. isGuest() — проверить является ли юзер гостем, а именно user_id == 0?
  4. getId() — получить ID юзера.
  5. getLoginName() — получить логин юзера.
  6. getProperties() — получить список всех свойств.
  7. getProperty($name) — получить заданное свойство.
  8. updateProperties(array $props) — обновить все свойства.
  9. updateProperty($name, $value) — обновить заданное свойство.
  10. updatePassword($password) — обновить пароль.

Защищенный метод:

  1. authenticate() – надо подумать, либо вызывать его из конструктора, либо вызывать после создания объекта User. разумеется если синглотон, то вызывать из коструктора.

Способы представления:

  1. Cookie — Считывается некоторый код с куки (токен).
  2. Session — каждый раз стартует сессия и действует, пока сессиия жива.
  3. HTTP Basic
  4. HTTP Digest

Алгоритм

  1. Создаётся объект Authentication\User.
  2. В конструкторе в зависимости от настройки конфигурации, выполняется попытка распознать пользовалея т.е. если type = cookie, то выполняется protected function cookieLogin(), если type = session, то выполняется protected function sessionLogin().
  3. При аутентификации через куки, первым делом смотрится наличие в куке уникального ключа (token).
  4. Если токен существует, то производится попытка прочитать данные юзера из сесии. Точнее будет сказать, если в сессии токен совпадает с токеном в куки, то принимаются данные юзера, которые хранятся в сессии.
  5. Если токен в сессии не совпадает с токеном в куки, то убивается и сессия и токен куки и выполняется редирект.
  6. Если токен в сессии пустой, то предпринимается попытка аутентифицироваться по токену в Базе Юзеров ( $this->Base->loginByToken($token); ).
  7. Ответ от loginByToken() имеет следующий формат: 1. stаtus — VALID, INVALID 2. data – массив с данными юзера. 3. message – сообщение об ошибке.
  8. Далее через объект User, получаем доступ к данным о пользователе через методы, указанные в главе «Аутентификация».

Регистрация

@todo продумать логику регистрации, если юзер представляется с помощью OpenID и т.д.

@ Открытые вопросы

  1. Как выполнять логику смены пароля?
  2. Стоит ли профили добавлять в базовую поставку, в принципе они немного похожи на атрибуты аккаунта, но всёже весьма специфичные.
  3. Класс Authentication\User видимо должен быть синглотоном...
  4. В компоненте аутентификации объект базы юзеров надо придумать как юзать с отложенной инициализацией... т.е. как-то внедрить DI.
  5. Возможно есть смысл сделать возможность прикрепления нескольких е-майлов к одному аккаунту, а также один из них указывать как основной.

@ todo

  1. Учет неудачных попыток входа в систему (failed attempt) и сброс пароля.
  2. Защита от поддельных токенов.

Структуры БД (MySQL)

Аутентификация

CREATE TABLE `users` (
  `user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `is_locked` tinyint(1) NOT NULL DEFAULT '0',
  `email` varchar(48) DEFAULT NULL,
  `create_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Дата создания аккаунта',
  `expired` tinyint(1) NOT NULL DEFAULT '0',
  `expires_at` datetime DEFAULT NULL,
 
  -- Опциональные поля.
 
  `nickname` varchar(100) NOT NULL COMMENT 'Псевдоним @OPTIONAL',
  `fullname` varchar(100) DEFAULT NULL COMMENT 'Полное имя @OPTIONAL',
  `dob` date DEFAULT NULL COMMENT 'Дата рождения @OPTIONAL',
  `gender` enum('M','F') DEFAULT NULL COMMENT 'Пол @OPTIONAL',
  `language` varchar(2) DEFAULT NULL COMMENT '@OPTIONAL',
  `timezone` varchar(100) DEFAULT NULL COMMENT 'Временная зона. @OPTIONAL',
  `create_on_site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'С какого проекта создан аккаунт @OPTIONAL',
 
  PRIMARY KEY (`user_id`),
  UNIQUE KEY `email` (`email`),
  KEY `is_locked` (`is_locked`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='Учетные записи пользователей' AUTO_INCREMENT=1 ;
 
CREATE TABLE `users_logins` (
  `user_id` int(10) UNSIGNED NOT NULL,
  `login` varchar(100) NOT NULL,
  `password` varchar(90) DEFAULT NULL,
  `salt` varchar(32) DEFAULT NULL,
  `hash_version` tinyint(3) UNSIGNED DEFAULT NULL COMMENT 'Версия алгоритма хеширования',
  `is_locked` tinyint(1) NOT NULL DEFAULT '0',
  `create_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Дата создания логина',
  `create_on_site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0' COMMENT 'С какого проекта создан логин @TODO возможно вынести, а может и оставить.',
  `expired` tinyint(1) NOT NULL DEFAULT '0',
  `expire_at` datetime DEFAULT NULL,
  PRIMARY KEY (`login`),
  KEY `password` (`password`),
  KEY `is_active` (`is_locked`),
  KEY `hash_version` (`hash_version`),
  KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Логины пользователей';
 
CREATE TABLE `users_tokens` (
  `user_id` int(10) UNSIGNED NOT NULL,
  `site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0',
  `login` varchar(100) NOT NULL,
  `token` varchar(255) NOT NULL,
  `valid_to_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Валиден до даты',
 
  PRIMARY KEY (`site_id`,`token`),
  KEY `valid_to_datetime` (`valid_to_datetime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Токены для утентификации через cookie';

Тестовые данные:

-- Логины пользователей
 
INSERT INTO `users_logins` (`user_id`, `login`, `password`, `salt`, `hash_version`, `is_locked`, `create_datetime`, `create_on_site_id`, `expired`, `expire_at`) VALUES
(1, 'http://artem.id.mail.ru', NULL, NULL, NULL, 0, '2011-00-00 00:00:00', 0, 0, NULL),
(1, 'https://www.google.com/accounts/o8/id?id=khbhedwsUBusydfbgjsdhfb_ZdfgjBhyw3ehbhh', NULL, NULL, NULL, 0, '2012-00-00 00:00:00', 0, 0, '2012-06-12 17:55:55'),
(1, 'root', 'pSRvk1iSFWol6tPyvrt8ULb6A03pa3jT8LNsVv9eYC9DSQMFLL91dzHBNvPFUFuICMMvFqzYBnyDVaW+Eg3eRg==', 'rvmppg4hla80gw0c88wwkogkc8cg88c', 3, 0, '2011-00-00 00:00:00', 0, 0, NULL);

Локальные юзеры

CREATE TABLE `users_local` (
  `user_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0',
  `is_locked` tinyint(1) NOT NULL DEFAULT '0',
  `create_datetime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Дата создания аккаунта',
  `expired` tinyint(1) NOT NULL DEFAULT '0',
  `expires_at` datetime DEFAULT NULL,
 
  PRIMARY KEY (`user_id`,`site_id`),
  UNIQUE KEY `email` (`site_id`),
  KEY `is_locked` (`is_locked`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='Локальные пользователи платформы.';

Тестовые данные:

INSERT INTO `users_local` (`user_id`, `site_id`, `is_locked`, `create_datetime`, `expired`, `expires_at`) VALUES
(1, 1, 0, '0000-00-00 00:00:00', 0, NULL);

Авторизация

CREATE TABLE `roles` (
  `role_id` varchar(50) NOT NULL,
  `site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0',
  `pos` smallint(5) UNSIGNED NOT NULL DEFAULT '0',
  `descr` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`role_id`,`site_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Роли пользователей';
 
CREATE TABLE `roles_hierarchy` (
  `role_id` varchar(50) NOT NULL,
  `site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0',
  `parent_role_id` varchar(50) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Иерархия ролей';
 
CREATE TABLE `roles_users_relation` (
  `role_id` varchar(50) NOT NULL,
  `site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0',
  `user_id` int(10) UNSIGNED NOT NULL,
  PRIMARY KEY (`role_id`,`site_id`,`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Связи ролей и юзеров.';

Тестовые данные:

INSERT INTO `roles` (`role_id`, `site_id`, `pos`, `descr`) VALUES
('ROLE_ADMIN', 1, 0, 'Админ'),
('ROLE_GUEST', 1, 0, 'Анонимный посетитель'),
('ROLE_NEWSMAKER', 1, 0, 'Новостеписатель'),
('ROLE_ROOT', 1, 0, 'Супер админ'),
('ROLE_USER', 1, 0, 'Зарегистрированный пользователь');
 
INSERT INTO `roles_hierarchy` (`role_id`, `site_id`, `parent_role_id`) VALUES
('ROLE_NEWSMAKER', 1, 'ROLE_USER');
 
INSERT INTO `roles_users_relation` (`role_id`, `site_id`, `user_id`) VALUES
('ROLE_ROOT', 1, 1);

Регистрация

CREATE TABLE `users_reg` (
  `user_reg_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
  `is_locked` tinyint(1) UNSIGNED NOT NULL DEFAULT '0',
  `email` varchar(48) NOT NULL,
  `properties` longtext COMMENT 'Дополнительные свойства',
 
  PRIMARY KEY (`user_reg_id`),
  UNIQUE KEY `email` (`email`),
  KEY `is_locked` (`is_locked`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Учетные записи пользователей ожидающие активации' AUTO_INCREMENT=1 ;
 
CREATE TABLE `users_reg_confirmation` (
  `user_reg_id` int(10) UNSIGNED NOT NULL,
  `login` varchar(100) NOT NULL,
  `password` varchar(90) NOT NULL,
  `salt` varchar(32) NOT NULL,
  `start_datetime` datetime NOT NULL,
  `expire_at` datetime NOT NULL,
  `key` varchar(50) NOT NULL,
 
  PRIMARY KEY (`user_reg_id`),
  UNIQUE KEY `login` (`login`),
  UNIQUE KEY `key` (`key`),
  KEY `expire_at` (`expire_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='Ключи подтверждения регистрации';

Лог активности юзеров

CREATE TABLE `users_activity_log` (
  `log_id` bigint(20) NOT NULL AUTO_INCREMENT,
  `site_id` mediumint(8) UNSIGNED NOT NULL DEFAULT '0',
  `user_id` int(10) UNSIGNED NOT NULL,
  `login` varchar(100) NOT NULL,
  `action` varchar(20) NOT NULL,
  `referer` text,
  `datetime` datetime NOT NULL,
  `ip` varchar(40) NOT NULL,
  `browser` varchar(50) NOT NULL,
  `browser_version` varchar(50) NOT NULL,
  `platform` varchar(50) NOT NULL,
  `user_agent` text NOT NULL,
 
  PRIMARY KEY (`log_id`,`site_id`),
  KEY `user_id` (`user_id`),
  KEY `login` (`login`),
  KEY `datetime` (`datetime`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COMMENT='Лог активности пользователей' AUTO_INCREMENT=1 ;

Тестовые данные:

INSERT INTO `users_activity_log` (`log_id`, `site_id`, `user_id`, `login`, `action`, `referer`, `datetime`, `ip`, `browser`, `browser_version`, `platform`, `user_agent`) VALUES
(1, 1, 1, 'root', 'cookie_login', 'http://site.com/', '2012-01-11 19:26:11', '127.0.0.1', 'Firefox', '3.6.22', 'Windows', 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22'),
(3, 1, 1, 'root', 'logout', 'http://site.com/', '2012-01-12 02:13:52', '127.0.0.1', 'Firefox', '3.6.22', 'Windows', 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22'),
(4, 1, 2, 'admin', 'login', 'http://site.com/user/', '2012-01-12 02:16:08', '127.0.0.1', 'Firefox', '3.6.22', 'Windows', 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22'),
(6, 1, 2, 'admin', 'cookie_login', NULL, '2012-01-14 08:34:03', '127.0.0.1', 'Firefox', '3.6.22', 'Windows', 'Mozilla/5.0 (Windows; U; Windows NT 6.1; ru; rv:1.9.2.22) Gecko/20110902 Firefox/3.6.22');

Восстановление пароля

@todo

Источник — «http://smart-core.org/wiki/Users»
Личные инструменты
Пространства имён
Варианты
Действия
Основные разделы
Ссылки
Навигация
Инструменты