Аутентификация через Mail.ru

Продолжаем цикл статей, посвящённых созданию аутентификации пользователей через социальные сети и сервисы. Сегодня посмотрим, как осуществить подобный функционал через сервис Mail.ru

Если кто пропустил предыдущие выпуски, то их можно найти по следующим ссылкам:

sourse

Заметка. Как и в предыдущих статьях, пример, созданный в данном уроке, предназначен для работы на локальном сервере.

Шаг 1. Добавление нового приложения

Для начала нам необходимо добавить новый сайт в нашу учётную запись сервиса Mail.ru. Сделать это можно пройдя по вот этой ссылке. Для работы примера вам нужно будет самим зарегистрировать новое приложение и ввести собственные параметры.

На открывшейся странице, в первую очередь, соглашаемся с правилами размещения сайтов. Далее заполняем форму:

Название будет "Mail.ru Auth". Адрес главной страницы - это тот url адрес страницы, где будет внедрён основной функционал: http://localhost/mailru-auth. Таким образом, на локальном сервере поместим наши файлы в каталог "mailru-auth".

Далее нажимаем на кнопку "Продолжить" и переходим к следующему шагу. На третьем шаге необходимо скачать файл receiver.html, поместить его в каталог вашего проекта и дать Mail.ru возможность проверить существование данного файла. Поскольку наш пример предназначен для работы на локальном сервере, то мы этого делать не будем. Просто нажимаем кнопку "Продолжить", и на следующей странице "Пропустить". Если же вы создаёте пример для приложения работающего на каком-то реальном сервере, то сначала пройдите процедуру проверки наличия файла receiver.html, иначе функциональность вашего примера может быть ограничена.

Итак, после успешного добавления сайта в сервис Mail.ru, нам должно выдастся следующее сообщение со специальными параметрами:

Отсюда мы можем извлечь такие параметры, как `ID` приложения, `Приватный ключ` и`Секретный ключ`. Запишем их в специальные переменные в файле index.php:

<?php

$client_id = '702253'; // ID
$client_secret = '81fefec83a3ff8903af3fc4ae7bcc18e'; // Секретный ключ
$redirect_uri = 'http://localhost/mailru-auth'; // Ссылка на приложение
  

Шаг 2. Генерация ссылки для аутентификации

Для генерации ссылки нам потребуется адрес аутентификации и специальные параметры:

$url = 'https://connect.mail.ru/oauth/authorize';

$params = array(
    'client_id'     => $client_id,
    'response_type' => 'code',
    'redirect_uri'  => $redirect_uri
);

С помощью функции http_build_query, передав массив параметров, мы получим чередование ключей и значений, как в url адресе. Итак, генерируем ссылку и выводим на экран:

echo $link = '<p><a href="' . $url . '?' . urldecode(http_build_query($params)) . '">Аутентификация через Mail.ru</a></p>';

Тут же, в очередной раз, я воспользовался функцией urldecode. Если этого не сделать, то в сгенерированной ссылке могут появиться закодированные символы слешей, знаков двоеточия и так далее:

https://connect.mail.ru/oauth/authorize?client_id=702253&client_secret=81fefec83a3ff8903af3fc4ae7bcc18e&grant_type=authorization_code&code=81c3a267c791b2f451ffdaa54c8abe31&redirect_uri=http%3A%2F%2Flocalhost%2Fmailru-auth

Если же мы пропустим данную строку через функцию urldecode, то получим:

https://connect.mail.ru/oauth/authorize?client_id=702253&client_secret=81fefec83a3ff8903af3fc4ae7bcc18e&grant_type=authorization_code&code=81c3a267c791b2f451ffdaa54c8abe31&redirect_uri=http://localhost/mailru-auth

Ссылка для аутентификации готова. Если мы сформировали все параметры верно и получили правильный url, то пройдя по ссылке, будем перенаправлены по адресу, указанному в настройках приложения ('http://localhost/mailru-auth'). Как и в предыдущих случаях (при работе с Вконтакте и Одноклассниками), к этому адресу будет прикреплён специальный параметр code:

// Пример. В вашем случае код будет другой
http://localhost/mailru-auth/?code=5adc5521461df2b28be76b5cfdd6c7e5

Шаг 3. Получение токена

Начинать процедуру аутентификации мы можем в том случае, если к нам пришёл параметр code. Он нам нужен для того, чтобы получить специальный токен доступа, с помощью которого, в дальнейшем, мы достанем информацию о пользователе.

В первую очередь, снова сформируем параметры для этого запроса. Нам потребуется передать параметры: `client_id` - id приложения; `client_secret` - секретный ключ; `grand_type`, равный значению "authorization_code" - код активации; `code` - url параметр, пришедший от Mail.ru; `redirect_uri` - страница, на которую будет возвращён пользователь:

if (isset($_GET['code'])) {
    $result = false;

    $params = array(
        'client_id'     => $client_id,
        'client_secret' => $client_secret,
        'grant_type'    => 'authorization_code',
        'code'          => $_GET['code'],
        'redirect_uri'  => $redirect_uri
    );

    $url = 'https://connect.mail.ru/oauth/token';
}

Далее нам нужно отправить POST запрос на адрес https://connect.mail.ru/oauth/token, передав перечисленные параметры. В PHP выполнить POST запрос можно с помощью создания curl запроса:

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, urldecode(http_build_query($params)));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$result = curl_exec($curl);
curl_close($curl);

$tokenInfo = json_decode($result, true);

При успешном выполнении запроса в переменную $tokenInfo будет записан ответ от Mail.ru в JSON формате. Данная строка содержит 5 параметров: refresh token - маркер обновления информации, expires_in - время жизни токена, access_token, который мы будем использовать в следующих запросах для извлечения информации о пользователе, token_type - тип токена, x_mailru_vid - id пользователя в системе Mail.ru, который пытается авторизоваться:

{"refresh_token":"3d6c0c97abc7ce4a0a07a2950cf41a9f","expires_in":86400,"access_token":"bd0773b8b4f34394feec2f0ad3420968","token_type":"bearer","x_mailru_vid":"11138941216447863497"}

Для того чтобы мы далее могли работать с данными параметрами, декодируем JSON строку с помощью функции json_decode и помещаем данные в массив, передав в качестве второго аргумента true.

Шаг 4. Получение информации о пользователе

Теперь, когда у нас есть параметры access_token, мы можем сделать запрос к Mail.ru API и получить информацию о пользователе. Перед тем, как мы подготовим массив с параметрами, которые в последствии превратим во фрагмент url строки, нам нужно сформировать специальную `подпись` запроса $sign с помощью хэша md5;

if (isset($tokenInfo['access_token'])) {
    $sign = md5("app_id={$client_id}method=users.getInfosecure=1session_key={$tokenInfo['access_token']}{$client_secret}");

    $params = array(
        'method'       => 'users.getInfo',
        'secure'       => '1',
        'app_id'       => $client_id,
        'session_key'  => $tokenInfo['access_token'],
        'sig'          => $sign
    );

В параметр method записываем название метода Mail.ru API, который вернёт нам информацию о пользователе; параметру secure ставим 1 - это нужно для безопасности. Далее в параметр app_id передаём id нашего приложения; в session_key записываем access_token - токен доступа, который мы достали по POST запросу в предыдущем шаге и конечно же подпись запроса (sig).

Для получения информации о пользователе сформированные параметры нам нужно отправить GET запросом по адресу http://www.appsmail.ru/platform/api:

$params = array(
    'method'       => 'users.getInfo',
    'secure'       => '1',
    'app_id'       => $client_id,
    'session_key'  => $tokenInfo['access_token'],
    'sig'          => $sign
);

$userInfo = json_decode(file_get_contents('http://www.appsmail.ru/platform/api' . '?' . urldecode(http_build_query($params))), true);

В результате, если всё было сделано успешно, то получим JSON ответ приблизительно следующего вида:

[
  {
    "pic_50":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar50",
    "friends_count":2,
    "pic_22":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar22",
    "nick":"Стас Протасевич",
    "is_verified":1,
    "is_online":0,
    "pic_big":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatarbig",
    "last_name":"Протасевич",
    "has_pic":1,
    "email":"stanislav.protasevich@mail.ru",
    "pic_190":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar190",
    "referer_id":"",
    "vip":0,
    "pic_32":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar32",
    "birthday":"03.07.1988",
    "referer_type":"",
    "link":"http://my.mail.ru/mail/stanislav.protasevich/",
    "last_visit":"1363274031",
    "uid":"11138941216447863497",
    "app_installed":1,
    "status_text":"",
    "pic_128":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar128",
    "sex":0,
    "pic":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar",
    "pic_small":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatarsmall",
    "pic_180":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar180",
    "pic_40":"http://avt.appsmail.ru/mail/stanislav.protasevich/_avatar40",
    "first_name":"Стас"
  }
]

Далее преобразуем JSON ответ в массив и проверим наличие в нём нулевого элемента с ключом uid. Если такой элемент есть, извлечём его из общего массива $userInfo с помощью метода array_shift:

if (isset($userInfo[0]['uid'])) {
    $userInfo = array_shift($userInfo);
    $result = true;
}

Полный код:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ru">
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
    <title></title>
</head>
<body>

<?php

$client_id = '702253'; // ID
$client_secret = '81fefec83a3ff8903af3fc4ae7bcc18e'; // Секретный ключ
$redirect_uri = 'http://localhost/mailru-auth'; // Ссылка на приложение

$url = 'https://connect.mail.ru/oauth/authorize';

$params = array(
    'client_id'     => $client_id,
    'response_type' => 'code',
    'redirect_uri'  => $redirect_uri
);

echo $link = '<p><a href="' . $url . '?' . urldecode(http_build_query($params)) . '">Аутентификация через Mail.ru</a></p>';

if (isset($_GET['code'])) {
    $result = false;

    $params = array(
        'client_id'     => $client_id,
        'client_secret' => $client_secret,
        'grant_type'    => 'authorization_code',
        'code'          => $_GET['code'],
        'redirect_uri'  => $redirect_uri
    );

    $url = 'https://connect.mail.ru/oauth/token';

    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt($curl, CURLOPT_POST, 1);
    curl_setopt($curl, CURLOPT_POSTFIELDS, urldecode(http_build_query($params)));
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
    $result = curl_exec($curl);
    curl_close($curl);

    $tokenInfo = json_decode($result, true);

    if (isset($tokenInfo['access_token'])) {
        $sign = md5("app_id={$client_id}method=users.getInfosecure=1session_key={$tokenInfo['access_token']}{$client_secret}");

        $params = array(
            'method'       => 'users.getInfo',
            'secure'       => '1',
            'app_id'       => $client_id,
            'session_key'  => $tokenInfo['access_token'],
            'sig'          => $sign
        );

        $userInfo = json_decode(file_get_contents('http://www.appsmail.ru/platform/api' . '?' . urldecode(http_build_query($params))), true);
        if (isset($userInfo[0]['uid'])) {
            $userInfo = array_shift($userInfo);
            $result = true;
        }
    }
}


?>

</body>
</html>

Шаг 5. Извлечение информации о пользователе

Теперь извлекать информацию о пользователе мы можем из массива, хранящегося в переменной $userInfo, по ключам, которые вы можете найти в листинге JSON ответа последнего GET запроса. Я выведу лишь несколько значений:

if ($result) {
    echo "Социальный ID пользователя: " . $userInfo['uid'] . '<br />';
    echo "Имя пользователя: " . $userInfo['nick'] . '<br />';
    echo "Email: " . $userInfo['email'] . '<br />';
    echo "Ссылка на профиль пользователя: " . $userInfo['link'] . '<br />';
    echo "Пол пользователя: " . $userInfo['sex'] . '<br />';
    echo "День Рождения: " . $userInfo['birthday'] . '<br />';
    echo '<img src="' . $userInfo['pic_small'] . '" />'; echo "<br />";
}

Шаг 6. Что же дальше?

На данном этапе дальнейшая последовательность действий остаётся за вами. Если у нас есть такая информация, как ID пользователя, в первую очередь, нам необходимо проверить его наличие в нашей базе данных. Если пользователя с таким ID не существует, то значит он авторизовался с нашего сайта впервые, и мы внесём его в базу. Если пользователь уже есть, можем проверить, не изменились ли какие-то данные о нём, например, имя или ещё что-то. Если да, обновим запись.

После этого, всё что нам осталось сделать, так это создать сессию и поместить в неё информацию о нашем пользователе.

$_SESSION['user'] = $userInfo;

На странице выхода из системы просто удаляем сессию с помощью функции unset.

Итог

Ещё один рецепт создания сторонней аутентификацией у вас в копилке.

P.S. В комментариях к предыдущим статьям многие просят показать, что делать дальше. Как заполнить базу данных, как организовать полный процесс... Я обязательно расскажу об этом в заключительной части цикла данных статей, а до этого нам предстоит ознакомиться с созданием подобного функционала ещё для нескольких соц сетей и сервисов.

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

Удачи!

Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: www.ruseller.com
Автор: Станислав Протасевич
Урок создан: 15 Марта 2013
Просмотров: 45095
Правила перепечатки


5 последних уроков рубрики "PHP"

  • Фильтрация данных с помощью zend-filter

    Когда речь идёт о безопасности веб-сайта, то фраза "фильтруйте всё, экранируйте всё" всегда будет актуальна. Сегодня поговорим о фильтрации данных.

  • Контекстное экранирование с помощью zend-escaper

    Обеспечение безопасности веб-сайта — это не только защита от SQL инъекций, но и протекция от межсайтового скриптинга (XSS), межсайтовой подделки запросов (CSRF) и от других видов атак. В частности, вам нужно очень осторожно подходить к формированию HTML, CSS и JavaScript кода.

  • Подключение Zend модулей к Expressive

    Expressive 2 поддерживает возможность подключения других ZF компонент по специальной схеме. Не всем нравится данное решение. В этой статье мы расскажем как улучшили процесс подключение нескольких модулей.

  • Совет: отправка информации в Google Analytics через API

    Предположим, что вам необходимо отправить какую-то информацию в Google Analytics из серверного скрипта. Как это сделать. Ответ в этой заметке.

  • Подборка PHP песочниц

    Подборка из нескольких видов PHP песочниц. На некоторых вы в режиме online сможете потестить свой код, но есть так же решения, которые можно внедрить на свой сайт.

^ Наверх ^