Выдано 134844 лицензии

Авторизация через OAuth

Авторизация через OAuth
#
shushpanchik
299
В версии 6.1.4 появилась возможность пользователям сайта входить на сайты HostCMS через протокол OAuth. В данной теме будет доступно обновление XSL и типовой личного кабинета без которого данный функционал не будет доступен после стандартного обновления системы HostCMS.

XSL "ЛичныйКабинетПользователя" был изменен, полный код нового шаблона:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0"
   xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
   xmlns:hostcms="http://www.hostcms.ru/"
   exclude-result-prefixes="hostcms">
   <xsl:output xmlns="http://www.w3.org/TR/xhtml1/strict" doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" encoding="utf-8" indent="yes" method="html" omit-xml-declaration="no" version="1.0" media-type="text/xml"/>
   
   <xsl:template match="/siteuser">
      
      <xsl:choose>
         <!-- Авторизованный пользователь -->
         <xsl:when test="@id > 0">
            <h1>Пользователь <xsl:value-of select="login" /></h1>
            
            <!-- Выводим меню -->
            <ul class="users">
               <xsl:apply-templates select="item"/>
            </ul>
         </xsl:when>
         <!-- Неавторизованный пользователь -->
         <xsl:otherwise>
            <div class="authorization">
               <h1>Личный кабинет</h1>
               
               <!-- Выводим ошибку, если она была передана через внешний параметр -->
               <xsl:if test="error/node()">
                  <div id="error">
                     <xsl:value-of select="error"/>
                  </div>
               </xsl:if>
               
               <form action="/users/" method="post">
                  <p>Пользователь:
                     <br /><input name="login" type="text" size="30" class="large" />
                  </p>
                  <p>Пароль:
                     <br /><input name="password" type="password" size="30" class="large" />
                  </p>
                  <p>
                     <label><input name="remember" type="checkbox" /> Запомнить меня на сайте.</label>
                  </p>
                  <input name="apply" type="submit" value="Войти" class="button" />
                  
                  <!-- Страница редиректа после авторизации -->
                  <xsl:if test="location/node()">
                     <input name="location" type="hidden" value="{location}" />
                  </xsl:if>
               </form>
               
            <p>Первый раз на сайте? — <a href="/users/registration/">Зарегистрируйтесь</a>!</p>
               
            <p>Забыли пароль? Мы можем его <a href="/users/restore_password/">восстановить</a>.</p>
            </div>
            
            <xsl:if test="count(site/siteuser_identity_provider)">
               <div class="authorization">
                  
                  <xsl:if test="count(site/siteuser_identity_provider[type = 1])">
                  
                     <h1>OAuth</h1>
                     
                     <xsl:for-each select="site/siteuser_identity_provider[image != '' and type = 1]">
                        <xsl:element name="a">
                           <xsl:attribute name="href">
                              ?oauth_provider=<xsl:value-of select="@id"/>
                           </xsl:attribute>
                           <img src="{dir}{image}" alt="{name}"/>
                        </xsl:element>&#160;
                     </xsl:for-each>
                  
                  </xsl:if>
               
                  <h1>OpenID</h1>
                  
                  <!-- Выводим ошибку, если она была передана через внешний параметр -->
                  <xsl:if test="provider_error/node()">
                     <div id="error">
                        <xsl:value-of select="provider_error"/>
                     </div>
                  </xsl:if>
                  
                  <xsl:if test="count(site/siteuser_identity_provider[type = 0])">
                  
                     <form action="/users/" method="post">
                        <p>Войти с помощью:</p>
                        <xsl:for-each select="site/siteuser_identity_provider[image != '' and type = 0]">
                           <label>
                              <input type="radio" name="identity_provider" value="{@id}">
                                 <xsl:if test="position() = 1">
                                    <xsl:attribute name="checked">checked</xsl:attribute>
                                 </xsl:if>
                              </input> <img src="{dir}{image}" alt="{name}" title="{name}" />
                           </label>
                        </xsl:for-each>
                        
                        <p>Логин в выбранном сервисе:
                           <br /><input name="openid_login" type="text" size="30" class="large" />
                        </p>
                        
                        <input name="applyOpenIDLogin" type="submit" value="Войти" class="button" />
                     </form>
                     
                     <form action="/users/" method="post">
                        <p>или введите OpenID вручную:
                           <br /><input name="openid" type="text" size="30" class="large" />
                        </p>
                        <input name="applyOpenID" type="submit" value="Войти" class="button" />
                     </form>
                  
                  </xsl:if>
                  
               </div>
            </xsl:if>
         </xsl:otherwise>
      </xsl:choose>
   </xsl:template>
   
   <xsl:template match="item">
      <li style="background: url('{image}') no-repeat 11px 5px">
         <a href="{path}">
            <xsl:value-of select="name"/>
         </a>
      </li>
   </xsl:template>
</xsl:stylesheet>


Настройки типовой динамической "Пользователи сайта" были изменены:

// Авторизация OAuth
   if(!is_null($oauth_provider = Core_Array::getGet('oauth_provider')))
   {
      try
      {
         Core_Session::start();
         Core_Array::set($_SESSION, 'oauth_provider', $oauth_provider);
         $oSiteuser_Oauth_Controller = Siteuser_Oauth_Controller::factory($oauth_provider);
         if(is_null($oSiteuser_Oauth_Controller))
         {
            throw new Exception('Class does not exist');
         }
         Core_Array::set($_SESSION, 'oauth_data', $oSiteuser_Oauth_Controller->execute());
         die();
      }
      catch (Exception $e){}
   }

   $bTwitter = !is_null($oauth_token = Core_Array::getGet('oauth_token')) && !is_null($oauth_verifier = Core_Array::getGet('oauth_verifier'));

   // Встречаем ответ Вконтакте/Facebook/Одноклассники/Google+/Яндекс/Mail.ru/Twitter
   if(!is_null($code = Core_Array::getGet('code')) || $bTwitter)
   {
      $oauth_provider = Core_Array::get($_SESSION, 'oauth_provider');

      $oSiteuser_Oauth_Controller = Siteuser_Oauth_Controller::factory($oauth_provider);

      if(is_null($oSiteuser_Oauth_Controller))
      {
         throw new Exception('Class does not exist');
      }

      if ($bTwitter)
      {
         $oSiteuser_Oauth_Controller->oauth_token_secret = Core_Array::get($_SESSION, 'oauth_data');
         $oSiteuser_Oauth_Controller->oauth_token = $oauth_token;
         $oSiteuser_Oauth_Controller->oauth_verifier = $oauth_verifier;
      }
      else
      {
         $oSiteuser_Oauth_Controller->code = $code;
      }

      $aResult = $oSiteuser_Oauth_Controller->execute();

      if(is_null(Core_Array::get($aResult, 'error')))
      {
         if (!is_null($user_id = Core_Array::get($aResult, 'user_id')))
         {
            $oCurrentSiteuser = NULL;
            $oSiteuser_Identity = Core_Entity::factory('Siteuser_Identity');
            $oSiteuser_Identity->queryBuilder()
               ->where('siteuser_identity_provider_id', '=', $oauth_provider)
               ->where('identity', '=', $user_id)
               ->limit(1);
            $aSiteuser_Identities = $oSiteuser_Identity->findAll(FALSE);
            if (!count($aSiteuser_Identities))
            {
               $oSite = Core_Entity::factory('Site', CURRENT_SITE);
            
               if(!is_null($user_login = Core_Array::get($aResult, 'login')))
               {
                  $oSiteuser = $oSite->Siteusers->getByLogin($user_login, FALSE);

                  $sUserLogin = is_null($oSiteuser)
                     ? $user_login
                     : '';
               }
               else
               {
                  $sUserLogin = '';
               }

               if(!is_null($user_email = Core_Array::get($aResult, 'email')))
               {
                  $oSiteuser = $oSite->Siteusers->getByEmail($user_email, FALSE);
                  
                  $sUserEmail = !is_null($oSiteuser)
                     ? $user_email
                     : '';
               }
               else
               {
                  $sUserEmail = '';
               }
               
               // Create new siteuser
               $oSiteuser = Core_Entity::factory('Siteuser');
               $oSiteuser->login = $sUserLogin;
               $oSiteuser->password = Core_Hash::instance()->hash(Core_Password::get(12));
               $oSiteuser->email = $sUserEmail;
               $oSiteuser->name = Core_Array::get($aResult, 'name', '');
               $oSiteuser->surname = Core_Array::get($aResult, 'surname', '');
               $oSiteuser->company = Core_Array::get($aResult, 'company', '');
               $oSiteuser->save();

               if (!is_null($sPicture = Core_Array::get($aResult, 'picture')) && $sPicture != '')
               {
                  // Ищем свойство аватара
                  $oSiteuser_Property_List = Core_Entity::factory('Siteuser_Property_List', CURRENT_SITE);
                  $oProperty = $oSiteuser_Property_List->Properties->getByname('Аватар', FALSE);

                  if(!is_null($oProperty))
                  {
                     // Папка назначения
                     $sDestinationFolder = $oSiteuser->getDirPath();

                     // Файл-источник
                     $sSourceFile = $sPicture;

                     // Создаем папку назначения
                     $oSiteuser->createDir();

                     // Файл из WEB'а, создаем временный файл
                     $sTempFileName = tempnam(CMS_FOLDER . TMP_DIR, "CMS");
                     // Копируем содержимое WEB-файла в локальный временный файл
                     file_put_contents($sTempFileName, file_get_contents($sSourceFile));

                     // Файл-источник равен временному файлу
                     $sSourceFile = $sTempFileName;

                     switch(Core_Image::exifImagetype($sSourceFile))
                     {
                        case 1:
                           $sExt = 'gif';
                        break;
                        case 2:
                           $sExt = 'jpeg';
                        break;
                        case 3:
                           $sExt = 'png';
                        break;
                        default:
                           $sExt = 'jpeg';
                        break;
                     }

                     $sTargetFileName = "property_{$oProperty->id}.{$sExt}";

                     // Создаем массив параметров для загрузки картинок элементу
                     $aPicturesParam = array();
                     $aPicturesParam['large_image_isset'] = TRUE;
                     $aPicturesParam['large_image_source'] = $sSourceFile;
                     $aPicturesParam['large_image_name'] = "avatar.{$sExt}";
                     $aPicturesParam['large_image_target'] = $sDestinationFolder . $sTargetFileName;
                     $aPicturesParam['large_image_preserve_aspect_ratio'] = TRUE;
                     $aPicturesParam['large_image_max_width'] = $oProperty->image_large_max_width;
                     $aPicturesParam['large_image_max_height'] = $oProperty->image_large_max_height;
                     $aPicturesParam['large_image_watermark'] = FALSE;
                     $aPicturesParam['create_small_image_from_large'] = FALSE;

                     $aPropertyValues = $oProperty->getValues($oSiteuser->id, FALSE);

                     $oProperty_Value = count($aPropertyValues)
                        ? $aPropertyValues[0]
                        : $oProperty->createNewValue($oSiteuser->id);

                     // Удаляем старое большое изображение
                     if ($oProperty_Value->file != '')
                     {
                        try
                        {
                           Core_File::delete($sDestinationFolder . $oProperty_Value->file);
                        } catch (Exception $e) {}
                     }

                     try
                     {
                        $aResult = Core_File::adminUpload($aPicturesParam);
                     }
                     catch (Exception $exc)
                     {
                        Core_Message::show($exc->getMessage(), 'error');
                        $aResult = array('large_image' => FALSE);
                     }

                     if ($aResult['large_image'])
                     {
                        $oProperty_Value->file = $sTargetFileName;
                        $oProperty_Value->file_name = '';
                     }

                     $oProperty_Value->save();

                     // Файл временный, подлежит удалению
                     try
                     {
                        Core_File::delete($sSourceFile);
                     } catch (Exception $e) {}
                  }
               }

               if($sUserLogin == '')
               {
                  $oSiteuser->login = 'id' . $oSiteuser->id;
                  $oSiteuser->save();
               }

               // Add siteuser's identity
               $oSiteuser_Identity = Core_Entity::factory('Siteuser_Identity');
               $oSiteuser_Identity->siteuser_identity_provider_id = $oauth_provider;
               $oSiteuser_Identity->identity = $user_id;
               $oSiteuser->add($oSiteuser_Identity);

               // Add into default group
               $oSiteuser_Group = $oSiteuser->Site->Siteuser_Groups->getDefault();
               if (!is_null($oSiteuser_Group))
               {
                  $oSiteuser_Group->add($oSiteuser);
               }
               $oSiteuser->activate();
            }
            else
            {
               $oSiteuser = $aSiteuser_Identities[0]->Siteuser;
            }
            $oSiteuser->setCurrent();
            $Siteuser_Controller_Show->setEntity($oSiteuser);
         }
         else
         {
            throw new Exception("Can't detect siteuser id!");
         }
      }
      else
      {
         $error = Core_Array::get($aResult, 'error');
         $error_description = Core_Array::get($aResult, 'error_description');
         throw new Exception("Error: {$error} - {$error_description}");
      }
   }


вставлять после строки
$Siteuser_Controller_Show = new Siteuser_Controller_Show(
      $oSiteuser
   );

Re: Авторизация через OAuth
#
kad
412
Вот если бы вы реализовали это чуть раньше, мне бы не пришлось плясать с бубном для реализации авторизации в модуле экспорта вконтакт Хотя, конечно, еще не понятно можно ли так авторизовать stand-alone приложение.
Команда разработчиков KAD Systems | Интеграция и нестандартные решения на совесть | Email: info@kad.systems Skype: kad.systems | http://kad.systems/ https://vk.com/kad_sys
Re: Авторизация через OAuth
#
shushpanchik
299
KAD,
боюсь, наша авторизация Вам не поможет, т.к. мы не храним токены доступа. Вам придётся переопределять класс и хранить токен где-то, дабы пользователю не нужно было каждый раз акцептировать запрос.
Re: Авторизация через OAuth
#
kad
412
shushpanchik,
это, определенно, наименьшая из возможных проблем.
Команда разработчиков KAD Systems | Интеграция и нестандартные решения на совесть | Email: info@kad.systems Skype: kad.systems | http://kad.systems/ https://vk.com/kad_sys
Re: Авторизация через OAuth
#
kvasiliy
352
В последнем обновлении написано "Предполагается, что свои приложения в каждой социальной сети Вы зарегистрировали"
где регистрировать приложение? например в яндексе или в одкл..
Re: Авторизация через OAuth
#
shushpanchik
299
kvasiliy,
воспользуйтесь инструкцией к соответствующей социальной сети. По запросу в гугл: "%SOC_NETW_NAME% регистрация приложения API"
Re: Авторизация через OAuth
#
shok-ds
15
Какие данные передаются из соцсетей на данный момент?
www.quatrox.ru
Re: Авторизация через OAuth
#
shushpanchik
299
shok-ds,
Вы можете увидеть это в конкретном классе, например:

\modules\siteuser\oauth\twitter\controller.php

return array(
            'user_id' => $oResponse->id,
            'email' => '',
            'name' => $oResponse->name,
            'surname' => '',
            'login' => $oResponse->screen_name,
            'company' => '',
            'picture' => $oResponse->profile_image_url
         );
Re: Авторизация через OAuth
#
Puma
509

Инстсрукции по регистрации на Одноклассиниках:
http://apiok.ru/wiki/pages/viewpage.action?pageId=50888859
http://apiok.ru/wiki/pages/viewpage.action?pageId=42476486
Email: golden-puma@yandex.ru, Skype: golden_puma
Re: Авторизация через OAuth
#
kad
412
1. Создал приложение ВК, ввел необходимые данные в /config/vkontakte.php
2. Перешел в ЛК на сайте.
3. Нажал на иконку
4. После чего попал на страницу личного кабинета, в которой написано "Пользователь id5" и все. При просмотре личных данных вижу, что никаких данных из вк взято не было.
Команда разработчиков KAD Systems | Интеграция и нестандартные решения на совесть | Email: info@kad.systems Skype: kad.systems | http://kad.systems/ https://vk.com/kad_sys
Авторизация