Тут кто-то не так давно просил плагин для авторизации через Loginza.
Поскольку мне пришлось с ней столкнуться, то делюсь своей разработкой.
Для начала пара слов о самой Логинзе. Тех кто не знает что это такое - могут посмотреть на сайте https://loginza.ru/
Логинза обеспечивает авторизацию тем посетителям вашего сайта, у которых есть аккаунты в наиболее популярных социальных сетях, почтовых сервисах и у OpenID провайдеров.
В предлагаемом мною решении, для привязки аккаунтов пользователей этих сетей и сервисов к аккаунту пользователя HostCMS используется адрес электронной почты. Этот параметр передается почти во всех способах авторизации через Логинзу, кроме авторизации через ВКонтакте.
На вашем сайте пользователь должен быть уже зарегистрирован, иначе после авторизации через Логинзу сайт вам сообщит что такой пользователь на сайте не зарегистрирован.
Также, если в разных сетях и сервисах у вас зарегистрированы аккаунты на разные email-адреса, то авторизоваться с помощью Логинзы вы сможете только с помощью того сервиса, в котором указанный email совпадает с тем, который был указан при регистрации на вашем сайте.
Впрочем, это-то все вполне логично и очевидно.
А вот социальная сеть ВКонтакте подложила нам свинью.
Она не передает информацию об электронных адресах своих пользователей, а отдает только идентификатор аккаунта пользователя в сети ВКонтакте. Поэтому в доп.свойствах пользователей создается свойство для хранения id ВКонтакте, а при первой авторизации через "ВКонтакт" HostCMS еще и вынуждена запрашивать у пользователя email, чтобы соотнести id аккаунта ВКонтакте с email аккаунта на вашем сайте. Это соответствие запоминается, и в следующий раз email спрашиваться уже не будет.
Доп.свойство для хранения id "ВКонтакта" создавать вручную не надо, предлагаемое решение создает его автоматически.
Код основан на ТДС "Пользователи сайта", взятой с демо-сайта HostCMS.
Все что вам нужно, это перейти в редактирование этой ТДС и заменить php-код во вкладках "Код страницы" и "Настройки страницы", а также указать три настроечных параметра.
Код страницы:
<?php
if (class_exists('SiteUsers')) {
$error = '';
$SiteUsers = &singleton('SiteUsers');
/* XSL шаблон для отображения списка элементов информационной системы */
$xsl_chamber = to_str($GLOBALS['LA']['xsl_chamber']);
/* Переходим в кабинет пользователя, если user авторизирован */
if ($user_id > 0) {
if (isset($_POST['apply']) || isset($_GET['location'])) {
$path = './?rand=' . rand(0, 99999);
// Путь ниже может быть заменен на путь форума
$user_path = $path;
$bIsForum = false;
/* Если user логинился с форума, то вернется на ту же страницу с которой логинился,
в противном случае попадёт в кабинет пользователя */
$forums_conference_id = to_int($_POST['conference_id']);
if ($forums_conference_id > 0) {
$forum = new Forums();
$path = $forum->GetConferencePath($forums_conference_id);
?>
<h1>Добро пожаловать!</h1>
<p>Вы можете продолжить работу в <b><a href='<?php echo $user_path ?>'>кабинете пользователя</a></b><?php if ($bIsForum) {
echo " или вернуться в <b><a href=\"$path\">форум</a></b>";
} ?>.
<br>
Если Ваш браузер поддерживает автоматическое перенаправление, через 5 секунд Вы <?php if ($bIsForum) {
echo "вернетесь в форум";
} else {
echo "перейдете в кабинет пользователя";
} ?>.
Если Вы не хотите ждать, перейдите по соответствующей ссылке.</p>
// Получим идентификаторы групп пользователей, в которой состоит текущий пользователь
$site_users_groups_row = $SiteUsers->GetGroupsForUser($user_id);
// Проверим, есть ли для текущей группы пользователей сайта доступные партнерские программы
$affiliate_res = $affiliate->GetAllAffiliatePlans($site_users_groups_row);
/* Получаем данные о пользователе */
$user_row = $SiteUsers->GetListPrimaryProperties($user_id);
if ($user_row) {
/* Отображает кабинет пользователя */
$SiteUsers->ShowUserOffice($xsl_chamber, $external_propertys);
/* Применяем изменения подписки почтовых рассылок */
if (isset($_POST['renewmaillist'])) {
$maillist = new Maillist();
$maillist->RenewMaillist($user_id, $_POST);
}
} else {
echo "Пользователь не найден!";
}
}
}
// Нажали кнопку войти
elseif (isset($_POST['apply'])) {
$site_user_login = to_str($_POST['site_user_login']);
// Получаем информацию о пользователе по логину
$site_user_row = $SiteUsers->GetSiteUserByLogin($site_user_login);
// Пользователь найден по логину и его активация подтверждена, но неверно задан пароль
if ($site_user_row && $site_user_row['site_users_confirmation'] == 1) {
$error = 'Ошибка! Неправильный пароль.';
} elseif ($site_user_row && $site_user_row['site_users_confirmation'] == 0) {
$error = 'Внимание! Регистрация Ваших данных не подтверждена.
В Ваш адрес было отправлено письмо с информацией об активации.';
// Повторно отправляем пользователю данные для подтверждения регистрации
$SiteUsers->SendRegistInf($param_registration);
}
// Пользователь ранее регистрировался, но его регистрация не подтверждена
else {
$error = 'Пользователь с такими параметрами не зарегистрирован.';
}
}
// перехватим код ошибки Loginza, если он есть
if (empty($error) && isset($GLOBALS['loginza_auth_error']))
$error = $GLOBALS['loginza_auth_error'];
if ($user_id <= 0) {
// если пользователь пытался авторизоваться по Loginza через Вконтакте и у нас на сайте нет пользователя с таким вкid
// то спросим у пользователя email
if (isset($GLOBALS['auth_step']) && $GLOBALS['auth_step'] =
'loginza_request_email') {
?>
<h1>Авторизация</h1>
<?php echo !empty($error) ? '<div id="error">' . $error . '</div>' : '' ?>
<form action="./" method="post">
<p>Для окончания авторизации, пожалуйста, укажите ваш адрес электронной почты.</p>
<input name="site_user_email" type="text" size="30" class="large_input" />
<div class="gray_button">
<div>
<input name="email_refinement" type="submit" value="Войти" />
</div>
</div>
</form>
<?
} else {
// иначе показываем обычную форму авторизации, в конце которой отображается виджет Loginza
?>
<h1>Личный кабинет</h1>
<?php echo !empty($error) ? '<div id="error">' . $error . '</div>' : '' ?>
<form action="/users/" method="post">
<p>Пользователь:
<br /><input name="site_user_login" type="text" size="30" class="large_input" />
</p>
<p>Пароль:
<br /><input name="site_user_password" type="password" size="30" class="large_input" />
</p>
<p>
<input name="remember_me" id="remember_me" type="checkbox" /> <label for="remember_me">Запомнить меня на сайте.</label>
</p>
<div class="gray_button">
<div>
<input name="apply" type="submit" value="Войти" />
</div>
</div>
</form>
<p>Первый раз на сайте? — <a href="/users/registration/">Зарегистрируйтесь</a>!</p>
<p>Забыли пароль? Мы можем его <a href="/users/restore_password/">восстановить</a>.</p>
<!-- начало кода для отображения виджета авторизации Loginza -->
<!-- конец кода для отображения виджета авторизации Loginza -->
<?php
}
}
} else {
?>
<h1>Пользователи сайта</h1>
<p>Функционал недоступен, приобретите более старшую редакцию.</p>
<p>Модуль «<a href="http://www.hostcms.ru/hostcms/modules/users/">Пользователи сайта</a>» доступен в редакциях «<a href="http://www.hostcms.ru/hostcms/editions/corporation/">Корпорация</a>» и «<a href="http://www.hostcms.ru/hostcms/editions/business/">Бизнес</a>».</p>
<?php
}
?>
Настройки страницы
<?php
// настройки для Логинзы
$loginza_widget_id = 1234; // значение берется из личного кабинета Логинзы
$loginza_signature = 'jsdhfjahhwehfwaehwejhjkafhwe8439r'; // значение берется из личного кабинета Логинзы
$GLOBALS['loginza_return_url'] = 'http://mysite.ru/login/'; // ссылка на узел структуры, к которому будет подключена эта ТДС
// конец настроек
$vk_property_name = 'vkontakte_id';
$loginza_errmsg_local_user_not_found_vk =
'На сайте не зарегистрирован пользователь, с таким сочетанием адреса электронной почты и id ВКонтакте.<br/>
Возможно, в вашем профиле на нашем сайте указан другой адрес электронной почты?<br/>
<br/>
Также вы можете попробовать <a href="./">авторизоваться другим способом</a>.';
$loginza_errmsg_local_user_not_found =
'На сайте не зарегистрирован пользователь, с таким адресом электронной почты.<br/>
Возможно, в вашем профиле на нашем сайте указан другой адрес электронной почты?';
$loginza_errmsg_data_integrity_err =
'Извините, при авторизации произошла ошибка контроля данных. Пожалуйста, попробуйте еще раз.';
$loginza_errmsg_invalid_email =
'Адрес электронной почты введен неправильно.<br/>
Возможно, вы сделали опечатку при вводе?<br/>
<br/>
Также вы можете попробовать <a href="./">авторизоваться другим способом</a>.';
$loginza_errmsg_auth_err_part1 =
'При авторзации через сервис Loginza произошла следующая ошибка: ';
$loginza_errmsg_auth_err_part2 =
' Пожалуйста, попробуйте повторить авторизацию еще раз.';
if (class_exists('shop')) {
$shop = &singleton('shop');
//$shop->use_cookies_read_control = true;
}
$user_id = 0;
if (class_exists('SiteUsers')) {
$kernel = &singleton('kernel');
$SiteUsers = &singleton('SiteUsers');
$DataBase = &singleton('DataBase');
// Нажали кнопку войти, или пришел токен от логинзы, или пришло уточнение адреса электронной почты
if (isset($_POST['apply']) || isset($_POST['token']) || isset($_POST['email_refinement'])) {
// если пришло уточнение адреса электронной почты
if (isset($_POST['email_refinement']) && isset($_POST['site_user_email'])) {
$email = to_str($_POST['site_user_email']);
// проверим правильность email
if (valid_email($email)) {
// запрос по определению id пользователя текущего сайта по email
$query = 'SELECT `site_users_id` FROM `site_users_table` WHERE `site_users_email` = "' .
$email . '" AND `site_id` = ' . CURRENT_SITE . ' LIMIT 0 , 1';
$result = $DataBase->select($query);
if ($result) {
//Если нашелся пользователь с таким email
// проверим подлинность авторизации loginza:
if (!session_id)
@session_start();
if (isset($_SESSION['loginza_auth_info']))
$loginza_userinfo = unserialize($_SESSION['loginza_auth_info']);
// проверим, а вдруг у найденного пользователя сохранен другой вкid?
$saved_value = $SiteUsers->GetValueExtraProperty($row['site_users_id'], $vk_property_name);
if (!$saved_value || $saved_value == $loginza_userinfo['uid']) {
// если вкid не сохранен или совпадает с полученным от Логинзы
// то мы определилиюзера верно
$user_id = $row['site_users_id'];
if (!$saved_value) {
// если вкid не сохранен, то сохраним его
// для этого определим id свойства для хранения вкid
$query = 'SELECT `site_users_extra_property_id`
FROM `site_users_extra_properties_table`
WHERE `site_users_extra_property_name` = "' .
$vk_property_name . '" AND `site_id` = ' . CURRENT_SITE . ' LIMIT 0 , 1';
$result = $DataBase->select($query);
if ($result && $DataBase->get_count_row()) {
// и если оно существует, то сохраним его id
$property_row = mysql_fetch_assoc($result);
$property_id = $property_row['site_users_extra_property_id'];
} else {
// а если не существует, то создадим его
$site_users_extra_property_id = 0;
$property_name = $vk_property_name;
$property_type = 1;
$property_title = 'ВКонтакте ID';
$property_size = '';
$property_rows = '';
$property_cols = '';
$property_checked = '';
$property_default_value = '';
$property_order = '';
$property_comment = '';
$lists_id = '';
$property_id = $SiteUsers->InsertExtraProperty($site_users_extra_property_id, $property_name,
$property_type, $property_title, $property_size, $property_rows, $property_cols,
$property_checked, $property_default_value, $property_order, $property_comment,
$lists_id);
}
//сохраним значение вкid для найденного пользователя.
$property_param = array();
$property_param['id'] = to_int($property_id);
$result = $SiteUsers->SetValueExtraProperty($user_id, $loginza_userinfo['uid'],
$property_param);
}
} else {
// если в профиле пользователя с данным email указан другой вкid, то что-то не так,
// и пользователя мы авторизовывать не будем.
$GLOBALS['loginza_auth_error'] = $loginza_errmsg_local_user_not_found_vk;
$GLOBALS['auth_step'] = 'loginza_request_email';
}
} else // если данные от Логинзы, сохраненные в сессию, не подходят к ключу,
// то кажется нас кто-то ломает! :)
// авторизация обломалась.
} else {
// если на сайте нет пользователя с таким email то авторизация обломалась.
$GLOBALS['loginza_auth_error'] = $loginza_errmsg_local_user_not_found;
$GLOBALS['auth_step'] = 'loginza_request_email';
}
} else {
// то что ввел юзер не похоже на email О_о
$GLOBALS['loginza_auth_error'] = $loginza_errmsg_invalid_email;
$GLOBALS['auth_step'] = 'loginza_request_email';
}
/*** преобразование объекта в массив ***/
$loginza_userinfo = objectToArray(json_decode($json));
if (!isset($loginza_userinfo['error_type'])) {
if (isset($loginza_userinfo['email']) && !empty($loginza_userinfo['email'])) {
$query = 'SELECT `site_users_id` FROM `site_users_table` WHERE `site_users_email` = "' .
to_str($loginza_userinfo['email']) . '" AND `site_id` = ' . CURRENT_SITE .
' LIMIT 0 , 1';
echo $query;
$result = $DataBase->select($query);
if ($result && $DataBase->get_count_row()) {
$row = mysql_fetch_assoc($result);
$user_id = to_int($row['site_users_id']);
} else
// если на сайте нет пользователя с таким email то авторизация обломалась.
$GLOBALS['loginza_auth_error'] = $loginza_errmsg_local_user_not_found;
}
$query = 'SELECT `site_users_id`
FROM `site_users_properties_table`
WHERE `site_users_extra_property_id` = (
SELECT `site_users_extra_property_id`
FROM `site_users_extra_properties_table`
WHERE `site_users_extra_property_name` = "' .
$vk_property_name . '"
AND `site_id` = ' . CURRENT_SITE . '
)
AND `site_users_property_value` = "' . $uid . '"
LIMIT 0 , 1';
$result = $DataBase->select($query);
if ($result && $DataBase->get_count_row()) {
$row = mysql_fetch_assoc($result);
$user_id = to_int($row['site_users_id']);
} else {
// ни для одного из пользователей сайта не указан такой id вконтакте.
// т.к. Вконтакте не передает информацию о email, надо будет запросить его у пользователя
if (!session_id)
@session_start();
$_SESSION['loginza_auth_info'] = serialize($loginza_userinfo);
$_SESSION['loginza_auth_info_key'] = md5(serialize($loginza_userinfo) . $loginza_signature);
// если у нас в сессии была сохранена инфа от Логинзы, то после успешной авторизации ее можно прибить.
if (isset($_SESSION['loginza_auth_info']))
unset($_SESSION['loginza_auth_info']);
if (isset($_SESSION['loginza_auth_info_key']))
unset($_SESSION['loginza_auth_info_key']);
}
/* Далее идет стандартный код настроек ТДС */
// Если была AJAX-авторизация -- отправим ответ
if (isset($_REQUEST['action'])) {
$JsHttpRequest = new JsHttpRequest('UTF-8');
// Получим идентификаторы групп пользователей, в которой состоит текущий пользователь
$site_users_groups_row = $SiteUsers->GetGroupsForUser($user_id);
// Проверим, есть ли для текущей группы пользователей сайта доступные партнерские программы
$affiliate_res = $affiliate->GetAllAffiliatePlans($site_users_groups_row);
// Отмена регистрации пользователем
if (isset($_GET['cancel'])) {
if ($SiteUsers->Unregistration($_GET['cancel'])) {
// Отменяем авторизацию текущего пользователя
$SiteUsers->UnsetCurrentSiteUser();
}
}
// Пользователь выходит из кабинета
if (isset($_GET['action']) && $_GET['action'] == 'exit') {
// Отменяем авторизацию текущего пользователя
$SiteUsers->UnsetCurrentSiteUser();
}
// Для страницы авторизации изменим TITLE
if ($SiteUsers->GetCurrentSiteUser() == 0) {
// Заголовок страницы
$kernel->set_title('Авторизация пользователя');
}
}
function objectToArray($object)
{
if (!is_object($object) && !is_array($object)) {
return $object;
}
if (is_object($object)) {
$object = get_object_vars($object);
}
return array_map('objectToArray', $object);
}
?>
Работа ТДС мною успешно проверена при авторизации с помощью Google, Yandex, Mail.ru, ВКонтакте, Loginza и WebMoney.
Твиттеров, фейсбуков и прочих нынче модных сервисов у меня нет, поэтому авторизацию через них я не проверял. Через остальные способы - тоже, так же за неимением аккаунтов.
Приглашаю всех тестировать работу Логинзы под HostCMS!
i_dmitriy2002, попросите ссылочку у formadesign, я, к сожалению, по некоторым причинам не могу указать здесь адрес сайта для которого я это реализовывал.