Блог

Yii и авторизация по OpenID.

При разработке одного из проектов, возникла задача дать возможность пользователю авторизоваться по OpenID. Так как проект писался на Yii, то я начал поиски компонента для этого фреймворка, который помог бы мне с этой задачей. Был задан вопрос на форуме ответа так и не последовало =(.
Было принято решение написать такой компонент (или что-то подобное) самому. Изначально я не планировал разбираться во всех тонкостях протокола OpenID, а потому решил просто написать обертку (врапер) для одной из существующих библиотек. В качестве такой библиотеки была выбрана вот эта openidenabled.com/php-openid/.
Возможно как раз из-за нехватки знаний о каких-то специфических тонкостях протокола и его реализации в этой библиотеке, привело к тому, что, полученный врапер работал (и сейчас работает) не совсем корректно. О том, что именно не так расскажу чуть позже.

После некоторого времени разработки я получил вот такой вот классик-оболочку, который очень легко и удобно (на мой взгляд) использовать.
Установка.
1. Скачиваем или делаем чекаут из SVN.
2. Распаковываем архив.
3. Каталог OpenId, содержащий библиотеку openidenabled.com/php-openid/ переносим в application.extensions
4. Сам класс-оболочку (YOpenIdAuth.php) переносим в любой каталог доступный Yii.

Установка завершена!

Как всем этим пользоваться.
Приведу пример своего котроллера (Код методов — не полный, только то, что касается OpenID):


class UserController extends YFrontMainController
{   
    public $auth;
    
    public function init()
    {        
        try{            
           $this->auth = new  YOpenIdAuth(Yii::app()->params['returnTo'],Yii::app()->params['trustRoot']);    
        }
        catch(Exception $e)
        {
            Yii::app()->user->setFlash('error','Ошибка авторизации!
Попробуйте позже!');
            $this->redirect(Yii::app()->homeUrl);
        }
    }



    public function actionLogin()
    {        
        $this->setTitle("Авторизация");       
        if(count($_GET) && isset($_GET['openid_identifier']))
        { 
          $auth = $this->auth;          
          try
          {
            $auth->authenticate($_GET['openid_identifier']);            
          }
          catch(Exception $e)
          {
            Yii::app()->user->setFlash('error',$e->getMessage()); 
          }          
        }        
        $this->render('login');
     }



     public function actionOpenIdFinal()
     {
        if(!count($_GET))
        {
            throw new YPageNotFoundException();
        }
        
        try
        {        
            $auth = $this->auth;            
            $openIdUser = $auth->finalAuth();            
        }
        catch(Exception $e)
        {
              Yii::app()->user->setFlash('error','При авторизации произошла ошибка!');
              Yii::log("Error OpenId Auth...".$e->getMessage(),CLogger::LEVEL_ERROR);
              $this->redirect(Yii::app()->homeUrl);
        }
     }
    
}  




Что же тут происходит:

1. В методе init() создается экземпляр моего класса-оболочки, в качестве параметров конструктор получает две строки:
— ссылка на которую произойдет редирект после авторизации на сайте OpeId — провайдера
— ссылка которая будет отображена на сайте OpenId — провайдера

 $this->auth = new YOpenIdAuth(Yii::app()->params['returnTo'],Yii::app()->params['trustRoot']);    

Эти параметры для удобства я вынес в конфигурационный файл приложения.
2. Экшн actionLogin() — он должен просто принять URL-адресс OpenID-провайдера и передать его в мтод authenticate() моего класса.

$auth->authenticate($_GET['openid_identifier']);            

3. Экшн actionOpenIdFinal() на этот экшн будет произведен редирект с сайта OpenID-провайдера. Т.е. именно в этом экшене необходимо обработать ответ от OpenID-провайдера и получить информацию о пользователе.

 $openIdUser = $auth->finalAuth();

В результате вызова этого метода в переменной $openIdUser получим массив информации о пользователе (если авторизация прошла корректно), содержащий следующие параметры:
— openIdLink — url OpenId-провайдера,
— nickname — ник пользователя,
— email — email пользователя,
— fullname — полное имя пользователя

Что же хочется исправить и для чего я опубликовал эту заметку.

1. Сейчас это просто класс и он имеет мало общего с компонентами Yii — хочется, что бы он соответствовал всем параметрам CComponent.
2. Возможно мой врапер использует не все возможности протокола OpenID и не все возможности используемой библиотеки.
3. Хочется провести полный рефакторинг кода.
4. Расширить его функциональность и конфигурируемость.
5. Заставить его работать с openid.mail.ru/ и стабильно работать с openid.yandex.ru/ (сейчас авторизация проходит не всегда)

Этот классик был написан буквально за пару часов, поэтому качество когда не совсем такое, какое хочется получить в финале.

Хочу призвать все русскоязычное (и не только) Yii-сообщество к написанию такого необходимого компонента.

В итоге хочется получить хороший и стабильный компонент для авторизации по OpenID в Yii.

Юпи! — CMS на Yii – http://yupe.ru

Исходный код – https://github.com/yupe/yupe

Присоединяйтесь!