Простой пример OpenId авторизации

#
Простой пример OpenId авторизации
Пока ждем реализацию блогов, я тут набросал весьма простую схемку разрешения комментариев пользователям, авторизованным с использованием OpenId от JanRain в условиях:
a) присутствия версии HostCMS-Халява
б) запрета комментирования незарегистрированным пользователям

Ничего сложного в этом нет, нового тоже - однако думаю, что для начинающих пригодится.

Итак, что мы имеем - ленту новостей, событий, словом, информационную систему, комментарии к которой хотелось бы видеть. Класса Users в Халяве нет, поэтому определить, кто именно заспамил ленту, открытую всем, будет проблематично.

Итак, что мы делаем:

1) Регистрируемся на http://rpxnow.com/ , читаем описанные там красоты и получаем скрипт для ссылки авторизации, который вставляем в свой макет. Скрипт будет выглядеть так:

<script type="text/javascript">
  var rpxJsHost = (("https:" == document.location.protocol) ? "https://" : "http://static.");
  document.write(unescape("%3Cscript src='" + rpxJsHost +
"rpxnow.com/js/lib/rpx.js' type='text/javascript'%3E%3C/script%3E"));
</script>
<script type="text/javascript">
  RPXNOW.overlay = true;
  RPXNOW.language_preference = 'ru';
</script>


сама ссылка на авторизацию - так

<a class="rpxnow" onclick="return false;"
href="https://ИМЯ-ВАШЕГО-ПРИЛОЖЕНИЯ.rpxnow.com/openid/v2/signin?token_url=URL-ВХОДА-ДЛЯ-ВАШЕГО-САЙТА">Войти, используя OpenId</a>


(В принципе, зарегистрировался я там исключительно из-за "красивых глаз" предлагаемого решения, написать подобную динамическую страницу не составляет никакого труда, вот, например, рабочий пример OpenId аутентификации от Давида Мзареуляна - http://hiero.ru/david/openid.primer/)

2) Также на http://rpxnow.com/ нам выдадут типичную php страницу входа на наш сайт. В нашем случае мы делаем динамическую страницу вида http://URL-ВАШЕГО-САЙТА/URL-ВХОДА-ДЛЯ-ВАШЕГО-САЙТА/ со следующим кодом в НАСТРОЙКАХ динамической страницы:


<?

// Below is a very simple PHP 5 script that implements the RPX token URL processing.
// The code below assumes you have the CURL HTTP fetching library.  

$rpxApiKey = 'ВАШ-КОД-API';  

if(isset($_POST['token'])) {

  /* STEP 1: Extract token POST parameter */
  $token = $_POST['token'];

  /* STEP 2: Use the token to make the auth_info API call */
  $post_data = array('token' => $_POST['token'],
                     'apiKey' => $rpxApiKey,
                     'format' => 'json');

  $curl = curl_init();
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_URL, 'https://rpxnow.com/api/v2/auth_info');
  curl_setopt($curl, CURLOPT_POST, true);
  curl_setopt($curl, CURLOPT_POSTFIELDS, $post_data);
  curl_setopt($curl, CURLOPT_HEADER, false);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  $raw_json = curl_exec($curl);
  curl_close($curl);


  /* STEP 3: Parse the JSON auth_info response */
  $auth_info = json_decode($raw_json, true);

  if ($auth_info['stat'] == 'ok') {
  
    /* STEP 3 Continued: Extract the 'identifier' from the response */
    $profile = $auth_info['profile'];
    $identifier = $profile['identifier'];
   
    if (isset($profile['photo']))  {
      $photo_url = $profile['photo'];
    }

    if (isset($profile['displayName']))  {
      $name = $profile['displayName'];     
    }

    if (isset($profile['email']))  {
      $email = $profile['email'];
  
    }

    /* STEP 4: Use the identifier as the unique key to sign the user into your system.
       This will depend on your website implementation, and you should add your own
       code here.
    */

$_SESSION['openidname']=$name;
$_SESSION['openidemail']=$email;

if (isset($_SESSION['lastknownpage'])) {

header('Location: http://URL-ВАШЕГО-САЙТА'.$_SESSION['lastknownpage'].'');
exit;

} else {

header('Location: http://URL-ВАШЕГО-САЙТА/');
exit;


}

/* an error occurred */

} else {

header('Location: http://URL-ВАШЕГО-САЙТА/СТРАНИЦА-ОШИБКИ/');
exit;

}

} else {

header('Location: http://URL-ВАШЕГО-САЙТА/СТРАНИЦА-ОШИБКИ/');
exit;

}


?>


Что мы делаем? В момент авторизации пользователь уходит на сайт RPX, в отдельном окне авторизуется на том ресурсе, OpenId которого он хочет использовать, затем возвращается на страницу входа вашего сайта, где мы перехватываем его имя и пароль в сессию. Так как хочется, чтобы пользователь после авторизации возвращался на ту же страницу, с которой начал, не забываем в начале макета вставить следующий код

<?php

if(session_id() == "")
{
session_start();
}

if (($_SERVER['REQUEST_URI'] != "/СТРАНИЦА-ВХОДА/")&&($_SERVER['REQUEST_URI'] != "/СТРАНИЦА-ВЫХОДА/")) {

$_SESSION['lastknownpage'] = $_SERVER['REQUEST_URI'];

}

?>


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

3) У нас уже есть авторизованный пользователь с именем и почтой в сессии. Теперь идем в типовые динамические страницы и видоизменяем страницу (в нашем случае это Типовые динамические страницы &#8594; Информационные системы &#8594; Информационная система)

Меняем

$form_user_name = to_str($_POST['comment_autor']);
$form_user_email = to_str($_POST['comment_email']);


на

if ((isset($_SESSION['openidname'])) && (isset($_SESSION['openidemail']))) {

$form_user_name = to_str($_SESSION['openidname']);
$form_user_email = to_str($_SESSION['openidemail']);

} else {

$form_user_name = to_str($_POST['comment_autor']);
$form_user_email = to_str($_POST['comment_email']);

}


и


$external_propertys['form_user_name'] = $form_user_name;
$external_propertys['form_user_email'] = $form_user_email;


на

  if ((isset($_SESSION['openidname'])) && (isset($_SESSION['openidemail']))) {

   $param['comment_autor'] = htmlspecialchars(to_str($_SESSION['openidname']));
   $param['comment_email'] = htmlspecialchars(to_str($_SESSION['openidemail']));

        } else {

        $param['comment_autor'] = htmlspecialchars(to_str($_POST['comment_autor']));
   $param['comment_email'] = htmlspecialchars(to_str($_POST['comment_email']));

       }



а также передаем в XSL значение аторизации OpenId пользователя, вставляя



...

if ((isset($_SESSION['openidname'])) && (isset($_SESSION['openidemail']))) {

               $external_propertys['OpenIdEnter'] = '1';

} else {

               $external_propertys['OpenIdEnter'] = '0';

}

...



4) Видоизменяем XSL-шаблон отображения единицы информационной системы, добавляя к условиям проверки права пользователя на добавление комментариев (не забываем, что в свойствах раздела права на комментарии выданы только зарегистрированным пользователям, сами комментарии включены) еще и проверку OpenId-авторизации, то есть что-то вроде



...

<!-- Если разрешено отображать формы добавления комментария
            1 - Только авторизированным
            2 - Всем
                                 не забываем про OpenIdEnter
            -->
                                <xsl:choose>

            <xsl:when test="(/document/show_add_comments/node() and ((/document/show_add_comments = 1 and /document/site_user_id &gt; 0)  or /document/show_add_comments = 2)) or /document/OpenIdEnter = 1">

...



и



...

<!-- Отображаем только авторизированным пользователям -->

<xsl:if test="(/document/show_add_comments/node() and ((/document/show_add_comments = 1 and /document/site_user_id > 0) or /document/show_add_comments = 2 or /document/OpenIdEnter = 1)) ">
                                                
<div class="cr" id="cr_{comment_id}">

...



Таким же образом можно убрать для OpenId-юзеров капчу, однако OpenId-боты отнюдь не лучше обычных.

5) Страница выхода. Хотя сессии и действуют только до закрытия браузера, кнопка выход не помешает. Делаем динамическую страницу http://URL-ВАШЕГО-САЙТА/СТРАНИЦА-ВЫХОДА/ со следующими НАСТРОЙКАМИ



<?php

if ((isset($_SESSION['openidname'])) || (isset($_SESSION['openidemail']))) {

unset($_SESSION['openidname']);
unset($_SESSION['openidemail']);

}

if (isset($_SESSION['lastknownpage'])) {

header('Location: http://URL-ВАШЕГО-САЙТА/'.$_SESSION['lastknownpage'].'');
exit;

} else {

header('Location: http://URL-ВАШЕГО-САЙТА/');
exit;

}

?>




Вот, собственно, и все.

Что мы имеем в результате? Имеем мы все плюсы OpenId, а также путь для воплощения массы фантазий, которые были ограничены необходимостью прописывать регистрацию и авторизацию для Халявы вручную.

Основной минус - OpenId-технологии не все доверяют.

Посмотреть, как это работает, можно здесь - http://jaybe.ru/blog/

Замечания, вопросы, комментарии приветствуются.
Авторизация