OpenID с версии 6.0.4

Модератор
#
OpenID с версии 6.0.4
Предлагаем протестировать реализацию OpenID, которая будет доступна с версии 6.0.4 для редакции Бизнес и Корпорация.
Модератор
#
Re: OpenID с версии 6.0.4
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">
               <h1>OpenId</h1>

               <!-- Выводим ошибку, если она была передана через внешний параметр -->
               <xsl:if test="provider_error/node()">
                  <div id="error">
                     <xsl:value-of select="provider_error"/>
                  </div>
               </xsl:if>

               <form action="/users/" method="post">
                  <p>Войти с помощью:</p>
                  <xsl:for-each select="site/siteuser_identity_provider[image != '']">
                     <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>
            </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>
Настройки типовой динамической:
<?php

if (Core::moduleIsActive('siteuser'))
{
   $oSiteuser = Core_Entity::factory('Siteuser')->getCurrent();
   is_null($oSiteuser) && $oSiteuser = Core_Entity::factory('Siteuser');

   $Siteuser_Controller_Show = new Siteuser_Controller_Show(
      $oSiteuser
   );

   // Авторизация по логину и паролю
   if (Core_Array::getPost('apply'))
   {
      $oSiteuser = $oSiteuser->getByLoginAndPassword(strval(Core_Array::getPost('login')), strval(Core_Array::getPost('password')));

      if (!is_null($oSiteuser))
      {
         if ($oSiteuser->active)
         {
            $expires = Core_Array::getPost('remember')
               ? 2678400 // 31 день
               : 86400; // 1 день

            $oSiteuser->setCurrent($expires);

            // Change controller's siteuser
            $Siteuser_Controller_Show->setEntity($oSiteuser);

            // Location
            !is_null(Core_Array::getPost('location')) && $Siteuser_Controller_Show->go(
               strval(Core_Array::getPost('location'))
            );
         }
         else
         {
            $Siteuser_Controller_Show->addEntity(
               Core::factory('Core_Xml_Entity')
                  ->name('error')->value('Пользователь не активирован!')
               );
         }
      }
      else
      {
         $Siteuser_Controller_Show->addEntity(
            Core::factory('Core_Xml_Entity')
               ->name('error')->value('Введите корректный логин и пароль!')
         );
      }
   }

   // Авторизация по логину OpenID
   if (Core_Array::getPost('applyOpenIDLogin'))
   {
      $oSiteuser_OpenID_Controller = Siteuser_OpenID_Controller::instance();

      $iSiteuser_Identity_Provider = intval(Core_Array::getPost('identity_provider'));

      $oSiteuser_Identity_Provider = Core_Entity::factory('Siteuser_Identity_Provider')->find($iSiteuser_Identity_Provider);

      if (is_null($oSiteuser_Identity_Provider->id))
      {
         $Siteuser_Controller_Show->addEntity(
            Core::factory('Core_Xml_Entity')
               ->name('provider_error')->value('Провайдер аутентификации не найден!')
         );
      }
      else
      {
         $sLogin = Core_Array::getPost('openid_login');
         $sIdentityURL = sprintf($oSiteuser_Identity_Provider->url, $sLogin);

         $oSiteuser_OpenID_Controller
            ->setIdentityURL($sIdentityURL)
            ->setTrustRoot('http://' . Core_Array::get($_SERVER, "HTTP_HOST"))
            ->setRequiredFields(array('email', 'fullname'))
            ->setOptionalFields(array('nickname', 'dob', 'gender', 'postcode', 'country', 'language', 'timezone'));

         if ($oSiteuser_OpenID_Controller->getOpenIDServer())
         {
            // Send Response from OpenID server to this script
            $oSiteuser_OpenID_Controller
               ->setReturnURL(
                  'http://' . Core_Array::get($_SERVER, "HTTP_HOST") . Core_Page::instance()->structure->getPath()
               )
               ->redirect();
         }
         else
         {
            $aError = $oSiteuser_OpenID_Controller->GetError();
            $Siteuser_Controller_Show->addEntity(
               Core::factory('Core_Xml_Entity')
                  ->name('provider_error')->value($aError['description'])
            );
         }
      }
   }

   // Авторизация по OpenID
   if (Core_Array::getPost('applyOpenID'))
   {
      $oSiteuser_OpenID_Controller = Siteuser_OpenID_Controller::instance();

      $sIdentityURL = Core_Array::getPost('openid');

      $oSiteuser_OpenID_Controller
         ->setIdentityURL($sIdentityURL)
         ->setTrustRoot('http://' . Core_Array::get($_SERVER, "HTTP_HOST"))
         ->setRequiredFields(array('email', 'fullname'))
         ->setOptionalFields(array('nickname', 'dob', 'gender', 'postcode', 'country', 'language', 'timezone'));

      if ($oSiteuser_OpenID_Controller->getOpenIDServer())
      {
         // Send Response from OpenID server to this script
         $oSiteuser_OpenID_Controller
            ->setReturnURL(
               'http://' . Core_Array::get($_SERVER, "HTTP_HOST") . Core_Page::instance()->structure->getPath()
            )
            ->redirect();
      }
      else
      {
         $aError = $oSiteuser_OpenID_Controller->GetError();
         $Siteuser_Controller_Show->addEntity(
            Core::factory('Core_Xml_Entity')
               ->name('provider_error')->value($aError['description'])
         );
      }
   }

   // Данные от сервера OpenID
   if (Core_Array::getGet('openid_mode') == 'id_res')
   {
      $oSiteuser_OpenID_Controller = Siteuser_OpenID_Controller::instance();

      $bValidate = $oSiteuser_OpenID_Controller
         ->setIdentityURL(Core_Array::getGet('openid_identity'))
         ->validateWithServer();

      // VALID
      if ($bValidate)
      {
         $sIdentity = $oSiteuser_OpenID_Controller->getIdentityUrl();

         $oSite = Core_Entity::factory('Site', CURRENT_SITE);

         $oSiteusers = $oSite->Siteusers;
         $oSiteusers->queryBuilder()
            ->select('siteusers.*')
            ->join('siteuser_identities', 'siteuser_identities.siteuser_id', '=', 'siteusers.id')
            ->where('siteuser_identities.identity', '=', $sIdentity)
            ->limit(1);

         $aSiteusers = $oSiteusers->findAll(FALSE);

         if (!count($aSiteusers))
         {
            // Create new siteuser
            $oSiteuser = Core_Entity::factory('Siteuser');

            $nickname = trim(strval($oSiteuser_OpenID_Controller->getAttribute('nickname')));

            if (strlen($nickname) && !is_null($oSite->Siteusers->getByLogin($nickname)))
            {
               $nickname = '';
            }

            $oSiteuser->login = $nickname;
            $oSiteuser->password = Core_Hash::instance()->hash(
               Core_Password::get(12)
            );
            $oSiteuser->email = trim(strval($oSiteuser_OpenID_Controller->getAttribute('email')));
            $oSiteuser->name = trim(strval($oSiteuser_OpenID_Controller->getAttribute('fullname')));
            $oSiteuser->save();

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

            // Add siteuser's identity
            $oSiteuser_Identity = Core_Entity::factory('Siteuser_Identity');
            $oSiteuser_Identity->identity = $sIdentity;
            $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 = $aSiteusers[0];
         }

         $oSiteuser->setCurrent();

         // Change controller's siteuser
         $Siteuser_Controller_Show->setEntity($oSiteuser);
      }
      elseif ($oSiteuser_OpenID_Controller->isError())
      {
         $aError = $oSiteuser_OpenID_Controller->GetError();
         $Siteuser_Controller_Show->addEntity(
            Core::factory('Core_Xml_Entity')
               ->name('provider_error')->value($aError['description'])
         );
      }
      else
      {
         $Siteuser_Controller_Show->addEntity(
            Core::factory('Core_Xml_Entity')
               ->name('provider_error')->value('Ошибка проверки подписи! Повторите авторизацию.')
         );
      }
   }

   // Подтверждение регистрации пользователем
   if (Core_Array::getGet('accept'))
   {
      $oSiteuser = Core_Entity::factory('Siteuser')->getByGuid(strval(Core_Array::getGet('accept')));

      if (!is_null($oSiteuser))
      {
         $oSiteuser->activate()->setCurrent();
         $Siteuser_Controller_Show->setEntity($oSiteuser);
      }
   }

   // Отмена регистрации пользователем
   if (Core_Array::getGet('cancel'))
   {
      $oSiteuser = Core_Entity::factory('Siteuser')->getByGuid(strval(Core_Array::getGet('cancel')));

      if (!is_null($oSiteuser))
      {
         // Отменяем авторизацию текущего пользователя
         $oSiteuser->delete()->unsetCurrent();

         // Set empty siteuser
         $Siteuser_Controller_Show->setEntity(Core_Entity::factory('Siteuser'));
      }
   }

   // Пользователь выходит из кабинета
   if (Core_Array::getGet('action') == 'exit')
   {
      // Отменяем авторизацию текущего пользователя
      $oSiteuser->unsetCurrent();

      // Set empty siteuser
      $Siteuser_Controller_Show->setEntity(Core_Entity::factory('Siteuser'));
   }

   Core_Page::instance()->object = $Siteuser_Controller_Show;
}
#
Re: OpenID с версии 6.0.4
Если на демо представлен окончательный вариант, то это чушь собачья, извините конечно за резкость. Все эти авторизации призваны облегчить вход пользователя на сайт до одного - двух кликов мышькой, а тут непонятно как заполняемая форма. Посмотрите хотя-бы мое (коллективное) последнее творение
*** модуль SLogin справа где-то посередине страницы (oAuth) или логинзу.
К этому надо стремиться. К тому же oAuth сейчас более популярен чем OpenId, а дальше OpenId совсем умрет или сольется с oAuth.
Модератор
#
Re: OpenID с версии 6.0.4
Arkadiy, отличный пример аналогичной формы: http://stackoverflow.com/users/login
Народ просил OpenId, мы предоставили. Нравиться Вам логинза - флаг в руки, используйте ее, извините за резкость.
#
Re: OpenID с версии 6.0.4
Народ в основном не знает чего просит, но все хотят удобства. Логинза мне не нравится, хотя я сделал авторизацию логинзой для джумлы и она стоит на моем сайте и я ей пользуюсь. В общем мне все равно чем авторизоваться, но мне лень нажимать кнопки, а тем более много кнопок. поймите, я не в укор вам. но продавать за деньги такое - я бы бесплатно не стал отдавать, очень сыро.
#
Re: OpenID с версии 6.0.4
А авторизация на http://stackoverflow.com/users/login решает свою задачу. Два клика и ты авторизован. Что еще нужно?
Модератор
#
Re: OpenID с версии 6.0.4
Arkadiy, из сообщения не вижу уведомления ни об одной ошибке, по которой делается вывод про "сыро".
у нас сколько же кликов, также выбрали иконку, ввели логин, принцип у OpenID-шных 1:1.
Что касается oAuth, то его интеграция запланирована на ближайшие обновления.
Спасибо за Ваше мнение.
#
Re: OpenID с версии 6.0.4
Сыро не в том смысле, что ошибки есть, а в том, что сама реализация (алгоритм) сырая.
Модератор
#
Re: OpenID с версии 6.0.4
Arkadiy писал(а):
Сыро не в том смысле, что ошибки есть, а в том, что сама реализация (алгоритм) сырая.
Вы считаете сам алгоритм OpenID сырым?
#
Re: OpenID с версии 6.0.4
Я считаю что такая реализация ничем не удобнее ввода логина/пароля, а тогда какой смысл в ней?
Авторизация