[EVO] Авторизация через uLogin

Часто проскакивает тема авторизации через соцсети с помощью uLogin, но как нужно, то невозможно ничего найти. Поэтому вот небольшой сниппет, который нужно вставить на страницу и указать в нем несколько параметров.
Дополнительно требует установленного сниппета weblogin.

<?php
$salt = '11111salt'; //для пароля - поменять!
$account_id = '20';//id ресурса "кабинет" для авторизованного  - поменять!
$fields = 'first_name,last_name,email'; //обязательные поля
$providers = 'vkontakte,odnoklassniki,mailru,facebook'; //список видимых провайдеров


$userId = $modx->getLoginUserId("web");
if ($userId) {//если пользователь авторизован, отправляем его сразу в кабинет
    $modx->sendRedirect($modx->makeUrl($account_id));
}


$out = '';
$out .= '
<script src="http://ulogin.ru/js/ulogin.js"></script>
<div id="uLogin" data-ulogin="display=panel;fields=' . $fields . ';providers='. $providers .';hidden=other;redirect_uri=' . $modx->config['site_url'] . ltrim($_SERVER['REQUEST_URI'], '/') . '"></div>
';
if (isset($_POST['token'])) {
    $s = file_get_contents('http://ulogin.ru/token.php?token=' . $_POST['token'] . '&host=' . $_SERVER['HTTP_HOST']);
    $user = json_decode($s, true);
    if (isset($user['error'])) {
        $out .= 'Произошла ошибка. Попробуйте еще раз';
    } else {
        if (!empty($user)) {
            $uid = isset($user['uid']) ? $user['uid'] : '';
            $provider = isset($user['network']) ? $user['network'] : '';
            $firstname = isset($user['first_name']) ? $user['first_name'] : '';
            $lastname = isset($user['last_name']) ? $user['last_name'] : '';
            $fullname = $lastname . ' ' . $firstname;
            $identity = isset($user['identity']) ? $user['identity'] : '';
            $password = md5($uid . $provider . $salt);
    
            if($uid != '' && $provider != ''){
                $username = $uid . '@' . $provider;
                $email = isset($user['email']) ? $user['email'] : $uid . '_' . $provider . '@test.ru';
                $fax = isset($user['profile']) ? $user['profile'] : ''; //внесем в это поле ссылку на профиль в соцсети
                if (!$userId && $fax != '') {//если пользователь не авторизован
                    //ищем, есть ли такой пользователь среди зарегистрированных
                    $q = $modx->db->query("SELECT id FROM " . $modx->getFullTableName('web_users') . " WHERE `username` = '" . $username . "' AND `password` = '" . $password . "' LIMIT 0, 1");
                    if($modx->db->getRecordCount($q) == 0){//если пользователь еще не зарегистрирован
                        $ins = $modx->db->insert(array('username'=>$username, 'password'=>$password), $modx->getFullTableName('web_users'));
                        if ($ins) {
                            $ins2 = $modx->db->insert(array('fullname'=>$fullname, 'email'=>$email, 'fax'=>$fax, 'comment'=>$identity, 'internalKey'=>$modx->db->getInsertId()), $modx->getFullTableName('web_user_attributes'));
                        }
                    }
                    //теперь осталось его только авторизовать
                    $_POST['username'] = $username;
                    $_POST['password'] = $uid . $provider . $salt;
                    $_POST['cmdweblogin']='Login';
                    $ok = $modx->runSnippet('WebLogin');
                    echo $ok;
                }
            }
        } 
    }
}
return $out;
?>

19 комментариев

avatar
Замечательное решение :)
есть гит под extras?
или самому создать?
avatar
Для полного счастья не хватает только привязки к нескольким соц сетям в личном кабинете
avatar
Ну с этим напряги, т.к. непонятно как однозначно идентифицировать одного и того же человека из разных соцсетей — ведь ни одного параметра который говорил бы что это именно он — к сожалению нет.
avatar
пологике только по Email

ну или привязывать уже внутри добавляя нужные идентификаторы
avatar
Так в том и проблема, что далеко не все соцсети отдают email :)
avatar
uLogin запрашивает ведь email для сайта
avatar
Запрашивает — если принудительно задать в настройках чтоб запрашивал. А по умолчанию — не запрашивает вроде. В общем пока это не сильно насущная вещь, судя по тому, что висит с 16 мая, отклики только вчера пошли ))))
avatar
создал тему. сразу пиши под ней коммент. так в ленту попадает. не все тонну почты просматривают по modx.im
avatar
Агама сам только заметил как понадобилось:) погуглил смотрю, о на modx.im есть )
avatar
Ну вот когда мне следующий раз понадобиться — тогда и доделаю заодно — чтобы можно было и нестандартные картинки как кнопку вызова использовать и задавать в вызове обязательные поля для запроса и т.п. :)))

upd — хотя поля уже есть — это $fields )))
Комментарий отредактирован 2014-07-29 15:48:59 пользователем webber
avatar
Здравствуйте честной народ. Изучаю MODx Evo около месяца, пришел к вопросу авторизации через соц сети. Как оказалось — Loginza с 2011 года как была куплена Яндексом, так и остановилась в развитии. Заинтересовал uLogin под Evo.
Можете пожалуйста пояснить как его использовать? У меня есть пара вопросов.

1. $salt = '11111salt'; //для пароля — поменять! — Что это и на что его менять?)
2. Вызываю сниппет так — [!uLogin!], веб-пользователь создается, но автоматически не авторизируеться (или он не должен автоматически авторизироваться? По логике вещей — должен).
3. Использую WebLoginPE, а не WebLogin, не в этом ли причина?
4. Последний вопрос, из-за чего, собственно не подходит Loginza. Нужно получать большое фото аватара пользователя, как это сделать?
avatar
1. Соль как часть пароля используется для его шифрования. Вы же не хотите чтобы ваш пароль можно было легко подобрать — потому поменяйте на что угодно и никому не говорите.

$password = md5($uid . $provider . $salt);
— тут вроде все очевидно для чего она и почему ее надо менять и держать в тайне :)))

2+3. Чтобы проходила авторизация нужно чтобы был установлен сниппет WebLogin. «Использовать» его нигде и не требуется, он просто должен быть в системе установлен.

4. Надо смотреть возвращаемые поля и дополнить сохранение пользователя нужным полем в этой части

if ($ins) {
    $ins2 = $modx->db->insert(array('fullname'=>$fullname, 'email'=>$email, 'fax'=>$fax, 'comment'=>$identity, 'internalKey'=>$modx->db->getInsertId()), $modx->getFullTableName('web_user_attributes'));
}
avatar
Спасибо, вроде все понятно)
Единственное что при авторизации через вк выдает ошибку,
(авторизация через фейсбук, гугл, одноклассники идут нормально)

MODX encountered the following error while attempting to parse the requested resource:
« Execution of a query to the database failed — Duplicate entry '9112971@vkontakte' for key 'username' »
SQL > INSERT INTO `****_****`.`modx_web_users` (`username`, `password`) VALUES('9112971@vkontakte', '9c18a6bdb8c3ac141257c50f5c0da19e')
Basic info
REQUEST_URI: mysite.ua/ulogin.html
Resource: [111]uLogin
Current Snippet: uLogin
Current Plugin: phx(OnParseDocument)
Referer: mysite.ua/ulogin.html
avatar
Так вы похоже соль поменяли и теперь у вас пытается создать того же пользователя с другим паролем. Во время работы соль менять нельзя.
avatar
Вы чертовски правы! Еще одно знание мне в копилочку :-)
Заработало!
avatar
А еще в строке указал видимых провайдеров
$providers = 'vkontakte,odnoklassniki,facebook'; //список видимых провайдеров
Но на странице отображаются ВК, ГУГЛ, Одноклассники (фейсбук и остальные в раскрывающемся списке)
avatar
Подключил данный сниппет и столкнулся с проблемой циклической переадресации. Авторизация пользователя проходит успешно но после этого получаю страницу с ошибкой указанной выше. Убираю вызов сниппета на странице и обновляю страницу: вижу успешное открытие под новым юзером из выбранной соц-сети. Можете подсказать как побороть проблему данную?
avatar
закоментировать


if ($userId) {//если пользователь авторизован, отправляем его сразу в кабинет
    $modx->sendRedirect($modx->makeUrl($account_id));
}


вообще реализовано не продуманно. посему лучше отключить, зарегаться всё равно не сможет
avatar
Для одного проекта нужно было сделать подключение соцетей уже после того, как пройдена авторизация (то, о чем Дима писал во втором комменте). Получилось следующее.
1) Расширяем табличку:
ALTER TABLE `modx_web_user_attributes` ADD `social` TEXT NOT NULL AFTER `editedon`;

2) Сниппет uLoginConnect который вставляем на страницу личного кабинета:
<?php
	$uid = $modx->getLoginUserId("web");
	if (!$uid) return;
	$providers = 'vkontakte,odnoklassniki,mailru,facebook,google'; //список видимых провайдеров

		if (isset($_POST['token'])) 
		{
			$s = file_get_contents('https://ulogin.ru/token.php?token=' . $_POST['token'] . '&host=' . $_SERVER['HTTP_HOST']);
			$user = json_decode($s, true);
		if (isset($user['error'])) 
		{
			$out .= 'Произошла ошибка. Попробуйте еще раз';
		} else 
		{
			$social_network = '';		
			if ($user['profile'])
			{
				if (strpos($user['profile'], 'vk.com')) $social_network = 'vkontakte';
				if (strpos($user['profile'], 'mail.ru')) $social_network = 'mailru';
				if (strpos($user['profile'], 'ok.ru')) $social_network = 'odnoklassniki';
				if (strpos($user['profile'], 'facebook.com')) $social_network = 'facebook';
				if (strpos($user['profile'], 'google.com')) $social_network = 'google';
			}
			$social_user = $modx->db->getValue('Select social from '.$modx->getFulltableName('web_user_attributes').' where internalKey='.$uid);
			$social_user_array = array();
			if ($social_user) $social_user_array = json_decode($social_user,true);

			$social_user_array[$social_network] = $user['uid'];
			$json = $modx->db->escape(json_encode($social_user_array));
			$modx->db->query('Update '.$modx->getFulltableName('web_user_attributes').' set `social`="'.$json.'" where internalKey='.$uid);	
		}		
	}
	$social_netwoks_user = $modx->db->getValue('Select social from '.$modx->getFulltableName('web_user_attributes').' where internalKey='.$uid);
	
	$already = array();
	if ($social_netwoks_user)
	{
		$social_netwoks_user_arr = json_decode($social_netwoks_user,true);		
		$out_providers = array();
		
		foreach(explode(',',$providers) as $provider) 
		{
			if (!$social_netwoks_user_arr[$provider]) $out_providers[] = $provider;
			else $already[] = $provider; 
		}
		$providers=implode(',',$out_providers);
	}
	if (count($already)) echo '<p>Вы уже подключен к: '.implode(',',$already).'</p>';
		
return '<script src="https://ulogin.ru/js/ulogin.js"></script><div id="uLogin" data-ulogin="display=panel;providers='. $providers .';hidden=;redirect_uri=' . $modx->config['site_url'] . ltrim($_SERVER['REQUEST_URI'], '/') . '"></div>';

3. На форму авторизации сниппет uLoginEnter:
<?php
	$uid = $modx->getLoginUserId("web");
	$page_id = 306;
	if ($uid) return;
	$providers = 'vkontakte,odnoklassniki,mailru,facebook,google'; //список видимых провайдеров
	echo '<script src="https://ulogin.ru/js/ulogin.js"></script><div id="uLogin" data-ulogin="display=panel;providers='. $providers .';hidden=;redirect_uri=' . $modx->config['site_url'] . ltrim($_SERVER['REQUEST_URI'], '/'). '"></div>';
	if (isset($_POST['token'])) 
	{
		$s = file_get_contents('https://ulogin.ru/token.php?token=' . $_POST['token'] . '&host=' . $_SERVER['HTTP_HOST']);
		$user = json_decode($s, true);
		if (isset($user['error'])) return 'Произошла ошибка. Попробуйте еще раз';
		else 
		{
			$social_network = '';		
			if ($user['profile'])
			{
				if (strpos($user['profile'], 'vk.com')) $social_network = 'vkontakte';
				if (strpos($user['profile'], 'mail.ru')) $social_network = 'mailru';
				if (strpos($user['profile'], 'ok.ru')) $social_network = 'odnoklassniki';
				if (strpos($user['profile'], 'facebook.com')) $social_network = 'facebook';
				if (strpos($user['profile'], 'google.com')) $social_network = 'google';
			}
			$uid = $modx->db->getValue('select internalKey from `modx_web_user_attributes` where `social` like \'%"'.$social_network.'":"'.$user['uid'].'"%\'');
			if ($uid)
			{
				include_once(MODX_BASE_PATH."assets/lib/MODxAPI/modUsers.php");	
				$user = new modUsers($modx);	
				$user->authUser($uid);
				header('Location: '.$modx->makeUrl($page_id));
				exit();
			}
			else return 'Пользователь не найден!';
		}		
	}


Вроде работает)
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.