- PVSM.RU - https://www.pvsm.ru -

HybridAuth для UMI.CMS. Авторизация через социальные сети на UMI.CMS

Я очень давно хотел для UMI сделать скрип отличный от loginza, так как считаю, что он не совсем удачный, по ряду причин (чисто субъективных). Могу ошибаться, если так и есть не закидывайте камнями.

Был вдохновлен одной из статей на habrahabr, к сожалению статья была удалена. Во всяком случае, ссылку на всякий пожарный оставлю — этой статьей [1]. В этой статье было рассказано в общем как подключать HybridAuth к своему сайта, и созрел для реализации метода и написания своей статьи.

Постараюсь рассмотреть реализацию авторизацию на UMI.CMS через популярную библиотеку HybridAuth.

Авторизация для UMI.CMS будет реализована через провайдеров:

  • Facebook
  • Twitter
  • Linkedin
  • Google+
  • Вконтакте


Статья по HybridAuth для UMI.CMS будет разделена на несколько статей:
1) Настройка полей пользователя
2) Установка и настройка HybridAuth
3) Установка скрипта HybridAuth + UMI.CMS
4) Корректировка шаблона

Настройка полей пользователя

Для начала следует зайти в шаблоны данных (модуль) и найти там тип данных «Пользователь»:
hybridauth-dlya-umi-cms-3 [2]

Добавить новое поле «Аватар» и «ID пользователя из соц. сети»:

hybridauth-dlya-umi-cms-4 [3]

hybridauth-dlya-umi-cms-5 [4]

hybridauth-dlya-umi-cms-6 [5]

Настройка пользователей закончена.

Установка и настройка HybridAuth

Скачать библиотеку можно здесь [6] (это оригинальные файлы), а здесь [7] доп. провадеров. По этой [8] ссылке можно скачать с уже добавленным vk.com(предлагаю использовать этот архив).

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

  • Facebook [9]
  • Twitter [10]
  • Google+ [11]
  • Вконтакте [12], сразу привожу ссылку на создание приложения, там проще всего
  • Linkedin.com [13], ссылка сразу на создание приложения

Далее, нужно сконфигурировать HybridAuth. Для этого откройте _http://ваш_сайт/hybridauth/install.php и выберите нужные сервисы. Хочу обратить внимание на то, что ребята разработавшие hybridauth сразу привели ссылки на создание приложений.

После того, как Вы внесли все настройки и сохранили, должны увидеть что-то вроде этого:

hybridauth-dlya-umi-cms-2 [14]

Теперь нужно добавить нового провайдера.

Если Вы воспользовались оригинальными файлами из репозитория, то нужно установить провайдера для vk.com (если взяли готовый архив, то пропустите настройку vk.com). Следует перейти по этой [15] ссылке и скачать файл. Его нужно разместить в директории hybridauthHybridProviders. В файле hybridauthconfig.php добавить участок кода и вписать id и secret, который предоставить вконтакте.

"Vkontakte" => array (
	"enabled" => true,
	"keys"    => array ( "id" => "", "secret" => "" )
),

Установка скрипта HybridAuth + UMI.CMS

Далее, нужно разместить в корне файл auth_with_social.php [16] со следующим содержанием:

session_start();

require_once('standalone.php');

$config = CURRENT_WORKING_DIR . '/hybridauth/config.php';
require CURRENT_WORKING_DIR . '/hybridauth/Hybrid/Auth.php';

$domain = cmsController::getInstance()->getCurrentDomain()->getHost(); // Получение домена
$users = cmsController::getInstance()->getModule("users"); // "Подключение" к модулю users
$data = cmsController::getInstance()->getModule("data"); // "Подключение" к модулю data


/*
 * /auth_with_social.php?login_with=_fb
 * /auth_with_social.php?login_with=_vk
 * /auth_with_social.php?login_with=_in
 * /auth_with_social.php?login_with=_gp
 * /auth_with_social.php?login_with=_tw
 * */

if( isset( $_GET["login_with"] ) ) {
    $login_with = $_GET["login_with"];

    try  {
        $hybridauth = new Hybrid_Auth($config);
        $adapter = false;

        switch ($login_with) {
            case "_fb":
                $adapter = $hybridauth->authenticate( "facebook" );
                break;
            case "_vk":
                $adapter = $hybridauth->authenticate( "vkontakte" );
                break;
            case "_in":
                $adapter = $hybridauth->authenticate( "linkedin" );
                break;
            case "_gp":
                $adapter = $hybridauth->authenticate( "google" );
                break;
            case "_tw":
                $adapter = $hybridauth->authenticate( "twitter" );
                break;
        }

        // Если в параметр передана "чушь" выдаем ошибку
        if(!$adapter) die( "<b>Ошибка про авторизации! Попробуйте еще раз.</b> ");

        $profile = $adapter->getUserProfile();

        // Если пользователь не залогинен - редирект
        if( !isset( $profile ) ){
            /* Редирект $profile случае запроса auth_with_social.php без параметров */
            $domain = cmsController::getInstance()->getCurrentDomain()->getHost();
            header ("Location: http://" . $domain);

        // Если пользователь залогинен, продолжаем работу :)
        } else {
            echo "Отладочная информация";
            echo "<pre>";
            print_r($profile);
            echo "</pre>";

            $objectTypes = umiObjectTypesCollection::getInstance();
            $objectTypeId	= $objectTypes->getBaseType("users", "user");
            $objectType = $objectTypes->getType($objectTypeId);


            $provider = $login_with; // Провайдер через который авторизовался пользователь
            $identifier = $profile->identifier;

            $login = $profile->email;
            $email = $profile->email;
            if(iconv_strlen($login) == 0) {
                $login = transliterate($profile->firstName);
                $login .= $profile->identifier;

                $email = $login . '@'. $domain;
            }
            $fname = $profile->firstName;
            $lname = $profile->lastName;
            $password = md5(generate_password(10));


            $sel = new selector('objects');
            $sel->types('object-type')->name('users', 'user');
            $sel->where('e-mail')->equals($email);
            $user = $sel->first;

            if( $user instanceof iUmiObject ) {
                permissionsCollection::getInstance()->loginAsUser($user);
                session_commit();

                header ("Location: http://" . $domain);
            } else {
                if(!preg_match("/.+@.+..+/", $email)) {
                    while(true) {
                        $email = $login.rand(1,100)."@".getServer('HTTP_HOST');
                        if($this->checkIsUniqueEmail($email)) {
                            break;
                        }
                    }
                }

                $object_id = umiObjectsCollection::getInstance()->addObject($login, $objectTypeId);
                $object = umiObjectsCollection::getInstance()->getObject($object_id);

                $object->setValue("login", $login);
                $object->setValue("password", md5($password));
                $object->setValue("e-mail", $email);
                $object->setValue("fname", ($fname));
                $object->setValue("lname", $lname);
                $object->setValue("loginza", $provider);
                $object->setValue("social_identifier", $identifier);
                $object->setValue("register_date", time());
                $object->setValue("is_activated", '1');
                $object->setValue("activate_code", md5(uniqid(rand(), true)));

                /* Создание аватара пользователя */
                $user_pic = "./files/users_upload/social_avatars/";
                $user_pic .= $identifier . $provider;

                $png_pos = strpos($profile->photoURL , '.png');
                $gif_pos = strpos($profile->photoURL , '.gif');

                if ( $png_pos !== false )
                    $user_pic .= ".png";
                elseif ( $gif_pos !== false )
                    $user_pic .= ".gif";
                else
                    $user_pic .= ".jpeg";


                // How to save facebook profile picture using php graph Api
                // http://goo.gl/zgL3iR

                // Сохранение изображения с заданного URL-адреса
                // http://goo.gl/VHeXk1
                $data = file_get_contents($profile->photoURL);
                $file = fopen($user_pic, 'wb');
                fputs($file, $data);
                fclose($file);


                if( file_exists("$user_pic") ) {
                    $oFile = new umiFile($user_pic);

                    if (!$oFile->getIsBroken()) {
                        $object->setValue("avatar", $oFile);
                    }

                }

                /* // Создание аватара пользователя */

                $_SESSION['cms_login'] = $login;
                $_SESSION['cms_pass'] = md5($password);
                $_SESSION['user_id'] = $object_id;

                session_commit();

                $group_id = regedit::getInstance()->getVal("//modules/users/def_group");
                $object->setValue("groups", Array($group_id));

                $data_module = cmsController::getInstance()->getModule('data');
                $data_module->saveEditedObject($object_id, true);

                $object->commit();

                header ("Location: http://" . $domain);
            }

        }

    } catch( Exception $e )  {
        /*$html = "Ошибка при авторизации. Информация об ошибки ниже: <br>";
        $html .= "<b>" . $e->getMessage() . "</b>";

        die( $html );*/

        header ("Location: http://" . $domain . '/authorization/?error=' . $e->getMessage());
    }
} else {
    /* Редирект в случае запроса auth_with_social.php без параметров */
    header ("Location: http://" . $domain);
}


/*
 * Генератор пароля
 * */
function generate_password($number) {
    $arr = array('a','b','c','d','e','f',
        'g','h','i','j','k','l',
        'm','n','o','p','r','s',
        't','u','v','x','y','z',
        'A','B','C','D','E','F',
        'G','H','I','J','K','L',
        'M','N','O','P','R','S',
        'T','U','V','X','Y','Z',
        '1','2','3','4','5','6',
        '7','8','9','0','-');
    // Генерируем пароль
    $pass = "";
    for($i = 0; $i < $number; $i++)
    {
        // Вычисляем случайный индекс массива
        $index = rand(0, count($arr) - 1);
        $pass .= $arr[$index];
    }
    return $pass;
}

/*
 * Транслит руского языка
 * */
function transliterate($input) {
    $gost = array(
        "Є"=>"YE","І"=>"I","Ѓ"=>"G","і"=>"i","№"=>"-","є"=>"ye","ѓ"=>"g",
        "А"=>"A","Б"=>"B","В"=>"V","Г"=>"G","Д"=>"D",
        "Е"=>"E","Ё"=>"YO","Ж"=>"ZH",
        "З"=>"Z","И"=>"I","Й"=>"J","К"=>"K","Л"=>"L",
        "М"=>"M","Н"=>"N","О"=>"O","П"=>"P","Р"=>"R",
        "С"=>"S","Т"=>"T","У"=>"U","Ф"=>"F","Х"=>"Kh",
        "Ц"=>"C","Ч"=>"CH","Ш"=>"SH","Щ"=>"SHH","Ъ"=>"'",
        "Ы"=>"Y","Ь"=>"","Э"=>"E","Ю"=>"YU","Я"=>"YA",
        "а"=>"a","б"=>"b","в"=>"v","г"=>"g","д"=>"d",
        "е"=>"e","ё"=>"yo","ж"=>"zh",
        "з"=>"z","и"=>"i","й"=>"j","к"=>"k","л"=>"l",
        "м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
        "с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"kh",
        "ц"=>"c","ч"=>"ch","ш"=>"sh","щ"=>"shh","ъ"=>"",
        "ы"=>"y","ь"=>"","э"=>"e","ю"=>"yu","я"=>"ya",
        " "=>"-","—"=>"-",","=>"-","!"=>"-","@"=>"-",
        "#"=>"-","$"=>"","%"=>"","^"=>"","&"=>"","*"=>"",
        "("=>"",")"=>"","+"=>"","="=>"",";"=>"",":"=>"",
        "'"=>"","""=>"","~"=>"","`"=>"","?"=>"","/"=>"",
        "\"=>"","["=>"","]"=>"","{"=>"","}"=>"","|"=>"", "."=>"-"
    );

    $string = strtr($input, $gost);

    return strtolower($string);
}

Далее в файл .htaccess добавить строку:

###### SOCIAL #####
RewriteRule ^hybridauth/(.*)*$ hybridauth/index.php?%{QUERY_STRING} [L]
###### // SOCIAL #####

Корректировка шаблона

Далее нужно добавить в шаблон ссылки, для авторизации через соц. сети. Нужно взять вот этот код:

<ul class="b-social-links">
	<li class="b-social-links__item">
		<a href="/auth_with_social.php?login_with=_fb" class="fb" title="Войти используя Facebook">Войти используя Facebook</a>
	</li>

	<li class="b-social-links__item">
		<a href="/auth_with_social.php?login_with=_vk" class="vk" title="Войти используя ВКонтакте">Войти используя ВКонтакте</a>
	</li>

	<li class="b-social-links__item">
		<a href="/auth_with_social.php?login_with=_in" class="in" title="Войти используя LinkedIn">Войти используя LinkedIn</a>
	</li>

	<li class="b-social-links__item">
		<a href="/auth_with_social.php?login_with=_gp" class="gp" title="Войти используя Google+">Войти используя Google+</a>
	</li>

	<li class="b-social-links__item">
		<a href="/auth_with_social.php?login_with=_tw" class="tw" title="Войти используя Twitter">Войти используя Twitter</a>
	</li>
</ul>

На этом с настройкой все.

Теперь хочу обратить внимание на то, если произошла ошибка при авторизации. Если такое произошло, то скрипт производит редирект на страницу /authorization/ с get параметром error.

Для того, чтобы показать пользователю ошибки, нужно создать страницу в структуре сайта и ее урл сделать /authorization/. Далее при помощи xslt отработать параметр error. TPL-шаблоназатор не рассматриваю.

Ссылки:

P.S. Если есть вопросы и непонятные моменты пишите комментарии.
P.S.S. Если Вы нашли ошибку, сообщите, я сразу исправлю. Старался побыстрее поделится опытом, может кому и пригодится.

Спасибо за внимание.

Автор: kibal4iw

Источник [19]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/cms/65333

Ссылки в тексте:

[1] этой статьей: http://habrahabr.ru/post/149187/

[2] Image: http://pontyk.com.ua/wp-content/uploads/2014/07/hybridauth-dlya-umi-cms-3.png

[3] Image: http://pontyk.com.ua/wp-content/uploads/2014/07/hybridauth-dlya-umi-cms-4.png

[4] Image: http://pontyk.com.ua/wp-content/uploads/2014/07/hybridauth-dlya-umi-cms-5.png

[5] Image: http://pontyk.com.ua/wp-content/uploads/2014/07/hybridauth-dlya-umi-cms-6.png

[6] здесь: http://hybridauth.sourceforge.net/index.html

[7] здесь: https://github.com/hybridauth/hybridauth/tree/master/additional-providers

[8] этой: http://pontyk.com.ua/wp-content/uploads/2014/07/hybridauth.zip

[9] Facebook: https://support.google.com/wildfire/answer/3467758?hl=ru&amp;ref_topic=3473113

[10] Twitter: https://support.google.com/wildfire/answer/3467713?hl=ru&amp;ref_topic=3473113

[11] Google+: https://support.google.com/wildfire/answer/3467714?hl=ru&amp;ref_topic=3473113

[12] Вконтакте: https://vk.com/editapp?act=create

[13] Linkedin.com: https://www.linkedin.com/secure/developer

[14] Image: http://pontyk.com.ua/wp-content/uploads/2014/07/hybridauth-dlya-umi-cms-2.png

[15] этой: https://github.com/hybridauth/hybridauth/tree/master/additional-providers/hybridauth-vkontakte/Providers

[16] auth_with_social.php: http://pontyk.com.ua/wp-content/uploads/2014/07/auth_with_social-2.zip

[17] Страница загрузки библиотеки и плагинов: http://hybridauth.sourceforge.net/download.html

[18] Страница проекта на GitHub: https://github.com/hybridauth/hybridauth

[19] Источник: http://habrahabr.ru/post/230365/