1
0
Fork 0
mirror of https://github.com/Oreolek/ifhub.club.git synced 2024-05-20 17:58:24 +03:00

Поддержка нескольких авторизаций для одного пользователя

This commit is contained in:
Mzhelskiy Maxim 2014-12-28 18:17:07 +07:00
parent 1fdc7d2398
commit e4bcd5391b
7 changed files with 218 additions and 72 deletions

View file

@ -79,12 +79,34 @@ class ModuleUser extends Module
* Проверяем есть ли у юзера сессия, т.е. залогинен или нет
*/
$sUserId = $this->Session_Get('user_id');
$sSessionKey = $this->Session_Get('session_key');
if ($sUserId and $oUser = $this->GetUserById($sUserId) and $oUser->getActivate()) {
if ($this->oSession = $oUser->getSession()) {
/**
* Проверяем сессию
*/
if ($oSession = $oUser->getSession()) {
$bSessionValid = false;
/**
* Сюда можно вставить условие на проверку айпишника сессии
* Т.к. у пользователя может быть несколько сессий (разные браузеры), то нужно дополнительно сверить
*/
$this->oUserCurrent = $oUser;
if ($oSession->getKey() == $sSessionKey and $oSession->isActive()) {
$bSessionValid = true;
} else {
/**
* Пробуем скорректировать сессию
*/
if ($oSession = $this->oMapper->GetSessionByKey($sSessionKey) and $oSession->getUserId() == $oUser->getId() and $oSession->isActive()) {
$bSessionValid = true;
$oUser->setSession($oSession);
}
}
if ($bSessionValid) {
/**
* Сюда можно вставить условие на проверку айпишника сессии
*/
$this->oUserCurrent = $oUser;
$this->oSession = $oSession;
}
}
}
/**
@ -548,7 +570,7 @@ class ModuleUser extends Module
*
* @param ModuleUser_EntityUser $oUser Объект пользователя
* @param bool $bRemember Запоминать пользователя или нет
* @param string $sKey Ключ авторизации для куков
* @param string $sKey Уникальный ключ сессии
* @return bool
*/
public function Authorization(ModuleUser_EntityUser $oUser, $bRemember = true, $sKey = null)
@ -556,12 +578,6 @@ class ModuleUser extends Module
if (!$oUser->getId() or !$oUser->getActivate()) {
return false;
}
/**
* Генерим новый ключ авторизаии для куков
*/
if (is_null($sKey)) {
$sKey = md5(func_generator() . time() . $oUser->getLogin());
}
/**
* Создаём новую сессию
*/
@ -572,12 +588,14 @@ class ModuleUser extends Module
* Запоминаем в сесси юзера
*/
$this->Session_Set('user_id', $oUser->getId());
$this->Session_Set('session_key', $this->oSession->getKey());
$this->oUserCurrent = $oUser;
/**
* Ставим куку
*/
if ($bRemember) {
$this->Session_SetCookie('key', $sKey, time() + Config::Get('sys.cookie.time'), false, true);
$this->Session_SetCookie('key', $this->oSession->getKey(), time() + Config::Get('module.user.time_login_remember'), false,
true);
}
return true;
}
@ -592,8 +610,8 @@ class ModuleUser extends Module
return;
}
if (isset($_COOKIE['key']) and is_string($_COOKIE['key']) and $sKey = $_COOKIE['key']) {
if ($oUser = $this->GetUserBySessionKey($sKey)) {
$this->Authorization($oUser);
if ($oUser = $this->GetUserBySessionKey($sKey) and $oSession = $this->oMapper->GetSessionByKey($sKey) and $oSession->isActive()) {
$this->Authorization($oUser, true, $oSession->getKey());
} else {
$this->Logout();
}
@ -645,12 +663,23 @@ class ModuleUser extends Module
*/
public function Logout()
{
/**
* Закрываем текущую сессию
*/
if ($this->oSession) {
$this->oSession->setDateLast(date("Y-m-d H:i:s"));
$this->oSession->setIpLast(func_getIp());
$this->oSession->setDateClose(date("Y-m-d H:i:s"));
$this->oMapper->UpdateSession($this->oSession);
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('user_session_update'));
}
$this->oUserCurrent = null;
$this->oSession = null;
/**
* Дропаем из сессии
*/
$this->Session_Drop('user_id');
$this->Session_Drop('session_key');
/**
* Дропаем куку
*/
@ -688,17 +717,65 @@ class ModuleUser extends Module
* @param string $sKey Сессионный ключ
* @return bool
*/
protected function CreateSession(ModuleUser_EntityUser $oUser, $sKey)
protected function CreateSession(ModuleUser_EntityUser $oUser, $sKey = null)
{
/**
* Генерим новый ключ
*/
if (is_null($sKey)) {
$sKey = md5(func_generator() . time() . $oUser->getId());
}
/**
* Проверяем ключ сессии
*/
if ($oSession = $this->oMapper->GetSessionByKey($sKey)) {
/**
* Если сессия уже не активна, то удаляем её
*/
if (!$oSession->isActive()) {
$this->oMapper->DeleteSession($oSession);
unset($oSession);
}
}
if (!isset($oSession)) {
/**
* Проверяем количество активных сессий у пользователя и завершаем сверх лимита
*/
$iCountMaxSessions = Config::Get('module.user.count_auth_session');
$aSessions = $this->GetSessionsByUserId($oUser->getId());
$aSessions = array_slice($aSessions, ($iCountMaxSessions - 1 < 0) ? 0 : $iCountMaxSessions - 1);
foreach ($aSessions as $oSessionOld) {
$oSessionOld->setDateClose(date("Y-m-d H:i:s"));
$this->oMapper->UpdateSession($oSessionOld);
}
/**
* Проверяем количество всех сессий у пользователя и удаляем сверх лимита
*/
$iCountMaxSessions = Config::Get('module.user.count_auth_session_history');
$aSessions = $this->GetSessionsByUserId($oUser->getId(), false);
$aSessions = array_slice($aSessions, ($iCountMaxSessions - 1 < 0) ? 0 : $iCountMaxSessions - 1);
foreach ($aSessions as $oSessionOld) {
$this->oMapper->DeleteSession($oSessionOld);
}
}
$this->Cache_Clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('user_session_update'));
$this->Cache_Delete("user_session_{$oUser->getId()}");
$oSession = Engine::GetEntity('User_Session');
/**
* Создаем новую или обновляем данные у старой
*/
if (!isset($oSession)) {
$oSession = Engine::GetEntity('User_Session');
$oSession->setKey($sKey);
$oSession->setIpCreate(func_getIp());
$oSession->setDateCreate(date("Y-m-d H:i:s"));
}
$oSession->setUserId($oUser->getId());
$oSession->setKey($sKey);
$oSession->setIpLast(func_getIp());
$oSession->setIpCreate(func_getIp());
$oSession->setDateLast(date("Y-m-d H:i:s"));
$oSession->setDateCreate(date("Y-m-d H:i:s"));
if ($this->oMapper->CreateSession($oSession)) {
$this->oSession = $oSession;
return true;
@ -706,22 +783,9 @@ class ModuleUser extends Module
return false;
}
/**
* Получить список юзеров по дате последнего визита
*
* @param int $iLimit Количество
* @return array
*/
public function GetUsersByDateLast($iLimit = 20)
public function GetSessionsByUserId($iUserId, $bOnlyNotClose = true)
{
if ($this->IsAuthorization()) {
$data = $this->oMapper->GetUsersByDateLast($iLimit);
} elseif (false === ($data = $this->Cache_Get("user_date_last_{$iLimit}"))) {
$data = $this->oMapper->GetUsersByDateLast($iLimit);
$this->Cache_Set($data, "user_date_last_{$iLimit}", array("user_session_update"), 60 * 60 * 24 * 2);
}
$data = $this->GetUsersAdditionalData($data);
return $data;
return $this->oMapper->GetSessionsByUserId($iUserId, $bOnlyNotClose);
}
/**

View file

@ -87,6 +87,28 @@ class ModuleUser_EntitySession extends Entity
return $this->_getDataOne('session_date_last');
}
/**
* Возвращает дату закрытия сессии
*
* @return string|null
*/
public function getDateClose()
{
return $this->_getDataOne('session_date_close');
}
/**
* Проверяет факт активности сессии
*
* @return bool
*/
public function isActive() {
if ($this->getDateClose()) {
return false;
}
return true;
}
/**
* Устанавливает ключ сессии
@ -147,4 +169,14 @@ class ModuleUser_EntitySession extends Entity
{
$this->_aData['session_date_last'] = $data;
}
/**
* Устанавливает дату закрытия сессии
*
* @param string $data
*/
public function setDateClose($data)
{
$this->_aData['session_date_close'] = $data;
}
}

View file

@ -451,10 +451,11 @@ class ModuleUser_EntityUser extends Entity
$iSize .= 'crop';
}
if ( $this->getProfileAvatar() ) {
if ($this->getProfileAvatar()) {
return $this->Media_GetImageWebPath($this->getProfileAvatar(), $iSize);
} else {
return $this->Media_GetImagePathBySize(Config::Get('path.skin.assets.web') . '/images/avatars/avatar_' . ($this->getProfileSex() == 'woman' ? 'female' : 'male') . '.png', $iSize);
return $this->Media_GetImagePathBySize(Config::Get('path.skin.assets.web') . '/images/avatars/avatar_' . ($this->getProfileSex() == 'woman' ? 'female' : 'male') . '.png',
$iSize);
}
}
@ -469,7 +470,7 @@ class ModuleUser_EntityUser extends Entity
$aAvatars = array();
foreach (Config::Get('module.user.avatar_size') as $sSize) {
$aAvatars[ $sSize ] = $this->getProfileAvatarPath( $sSize );
$aAvatars[$sSize] = $this->getProfileAvatarPath($sSize);
}
return $aAvatars;

View file

@ -141,6 +141,41 @@ class ModuleUser_MapperUser extends Mapper
return null;
}
public function GetSessionByKey($sKey)
{
$sql = "SELECT
s.*
FROM
" . Config::Get('db.table.session') . " as s
WHERE
s.session_key = ?
";
if ($aRow = $this->oDb->selectRow($sql, $sKey)) {
return Engine::GetEntity('User_Session', $aRow);
}
return null;
}
public function GetSessionsByUserId($iUserId, $bOnlyNotClose = true)
{
$sql = "SELECT
s.*
FROM
" . Config::Get('db.table.session') . " as s
WHERE
s.user_id = ?d
{ and 1=?d and s.session_date_close is null }
ORDER BY session_date_last desc
";
$aRes = array();
if ($aRows = $this->oDb->select($sql, $iUserId, $bOnlyNotClose ? 1 : DBSIMPLE_SKIP)) {
foreach ($aRows as $aRow) {
$aRes[] = Engine::GetEntity('User_Session', $aRow);
}
}
return $aRes;
}
/**
* Создание пользовательской сессии
*
@ -173,10 +208,27 @@ class ModuleUser_MapperUser extends Mapper
$sql = "UPDATE " . Config::Get('db.table.session') . "
SET
session_ip_last = ? ,
session_date_last = ?
WHERE user_id = ?
session_date_last = ?,
session_date_close = ?
WHERE session_key = ?
";
$res = $this->oDb->query($sql, $oSession->getIpLast(), $oSession->getDateLast(), $oSession->getUserId());
$res = $this->oDb->query($sql, $oSession->getIpLast(), $oSession->getDateLast(), $oSession->getDateClose(),
$oSession->getKey());
return $this->IsSuccessful($res);
}
/**
* Удаление сессии
*
* @param ModuleUser_EntitySession $oSession
* @return int|bool
*/
public function DeleteSession(ModuleUser_EntitySession $oSession)
{
$sql = "DELETE FROM " . Config::Get('db.table.session') . "
WHERE session_key = ?
";
$res = $this->oDb->query($sql, $oSession->getKey());
return $this->IsSuccessful($res);
}
@ -195,9 +247,20 @@ class ModuleUser_MapperUser extends Mapper
$sql = "SELECT
s.*
FROM
" . Config::Get('db.table.session') . " as s
WHERE
s.user_id IN(?a) ";
(
SELECT
user_id, max(session_date_last) as max_date_last
FROM
" . Config::Get('db.table.session') . "
WHERE
user_id IN (?a)
GROUP BY user_id
) as s2,
" . Config::Get('db.table.session') . " as s
WHERE
s2.user_id = s.user_id and s2.max_date_last = s.session_date_last
";
$aRes = array();
if ($aRows = $this->oDb->select($sql, $aArrayId)) {
foreach ($aRows as $aRow) {
@ -293,31 +356,6 @@ class ModuleUser_MapperUser extends Mapper
return null;
}
/**
* Получить список юзеров по дате последнего визита
*
* @param int $iLimit Количество
* @return array
*/
public function GetUsersByDateLast($iLimit)
{
$sql = "SELECT
user_id
FROM
" . Config::Get('db.table.session') . "
ORDER BY
session_date_last DESC
LIMIT 0, ?d
";
$aReturn = array();
if ($aRows = $this->oDb->select($sql, $iLimit)) {
foreach ($aRows as $aRow) {
$aReturn[] = $aRow['user_id'];
}
}
return $aReturn;
}
/**
* Получить список юзеров по дате регистрации
*
@ -365,9 +403,9 @@ class ModuleUser_MapperUser extends Mapper
*/
public function GetCountUsersActive($sDateActive)
{
$sql = "SELECT count(*) as count FROM " . Config::Get('db.table.session') . " WHERE session_date_last >= ? ";
$result = $this->oDb->selectRow($sql, $sDateActive);
return $result['count'];
$sql = "SELECT DISTINCT user_id FROM " . Config::Get('db.table.session') . " WHERE session_date_last >= ? ";
$result = $this->oDb->select($sql, $sDateActive);
return $result ? count($result) : 0;
}
/**
@ -1356,7 +1394,7 @@ class ModuleUser_MapperUser extends Mapper
}
$sql = "SELECT
u.user_id
DISTINCT u.user_id
FROM
" . Config::Get('db.table.user') . " as u
{ JOIN " . Config::Get('db.table.geo_target') . " as g ON ( u.user_id=g.target_id and g.country_id = ? ) }

View file

@ -157,6 +157,7 @@ $config['module']['user']['login']['max_size'] = 30; // Максимальное
$config['module']['user']['login']['charset'] = '0-9a-z_\-'; // Допустимые в имени пользователя символы
$config['module']['user']['time_active'] = 60 * 60 * 24 * 7; // Число секунд с момента последнего посещения пользователем сайта, в течение которых он считается активным
$config['module']['user']['time_onlive'] = 60 * 10; // Число секунд с момента последнего посещения пользователем сайта, в течение которых он считается "онлайн"
$config['module']['user']['time_login_remember'] = 60 * 60 * 24 * 7; // время жизни куки когда пользователь остается залогиненым на сайте, 7 дней
$config['module']['user']['usernote_text_max'] = 250; // Максимальный размер заметки о пользователе
$config['module']['user']['usernote_per_page'] = 20; // Число заметок на одну страницу
$config['module']['user']['userfield_max_identical'] = 2; // Максимальное число контактов одного типа
@ -173,6 +174,8 @@ $config['module']['user']['complaint_type'] = array( // Список типо
'other'
);
$config['module']['user']['rbac_role_default'] = 'user'; // Роль, которая автоматически назначается пользователю при регистрации
$config['module']['user']['count_auth_session'] = 4; // Количество разрешенных сессий пользователя (авторизаций в разных браузерах)
$config['module']['user']['count_auth_session_history'] = 10; // Общее количество сессий для хранения (значение должно быть больше чем count_auth_session)
// Модуль Comment
$config['module']['comment']['per_page'] = 20; // Число комментариев на одну страницу(это касается только полного списка комментариев прямого эфира)

View file

@ -744,4 +744,11 @@ INSERT INTO `prefix_topic_type` (`id`, `name`, `name_many`, `code`, `allow_remov
-- 17.12.2014
ALTER TABLE `prefix_user` CHANGE `user_settings_timezone` `user_settings_timezone` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL;
ALTER TABLE `prefix_user` ADD `user_admin` TINYINT(1) NOT NULL DEFAULT '0' AFTER `user_mail`, ADD INDEX (`user_admin`) ;
ALTER TABLE `prefix_user` ADD `user_admin` TINYINT(1) NOT NULL DEFAULT '0' AFTER `user_mail`, ADD INDEX (`user_admin`) ;
-- 27.12.2014
ALTER TABLE `prefix_session` DROP FOREIGN KEY `prefix_session_fk`;
ALTER TABLE `prefix_session` DROP INDEX user_id;
ALTER TABLE `prefix_session` ADD INDEX(`user_id`);
ALTER TABLE `prefix_session` ADD `session_date_close` DATETIME NULL DEFAULT NULL , ADD INDEX (`session_date_close`) ;

View file

@ -1,6 +1,7 @@
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
set_time_limit(0);
header('Content-Type: text/html; charset=utf-8');