Pull to refresh

Loginza — авторизация через Вконтакте, Facebook и др. OpenID серверы

Reading time5 min
Views6.2K

Вместо вступления


Про сервис Loginza на сегодняшний день не так и много
информации, а которая имеется — в основном от самих разработчиков и достаточно сухо. Это
даже странно. Я хочу рассказать о собственном опыте разработки.
Мне пришлось вплотную столкнуться с решением проблемы авторизации на разрабатываемом
сайте через Facebook и ВКонтакте. Недолго погуглив, наткнулся на Логинзу. Присмотрелся и
решил попробывать.

Документация, хоть и присутствует, но, на мой взгляд, скудновата. Мало примеров. Есть готовые
модули авторизации для раскрученных движков. В этом своём посте я хотел бы вкратце
рассказать алгоритм, который применил я в своём проекте.


Подготовительный этап


Весь подготовительный этап сводится к просмотру демок (чтобы представлять конечный вид) и
регистрации в Логинзе. Регистрация простая, я зарегистрировался через свой Яндекс-аккаунт, на
почту моментально пришло письмо с подтверждением регистрации и ссылкой на активацию.
В интерфейсе личного кабинета Логинзы нужно зарегистрировать сайт. Затем потребуется
подтвердить права, разместив файл на сайт. Как в Яндекс-вебмастере (кстати, кто не знает —
Яндекс купил Логинзу).

После того, как права подтверждены, можно получить ID виджета, и секретный ключ виджета.
Они понадобятся для разработки скрипта авторизации. Также, в настройках необходимо
поставить галочку «безопасный режим». «Опасный режим», видимо был в прошлом, о
безопасности пару слов в конце поста.

Последний подготовительный шаг — получение HTML кода виджета. Это можно сделать всё на
той же странице управления «Мои виджеты».

image

Разработка базы


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

Следует понимать, что авторизация «через Логинзу» — это всего лишь прослойка между
пользователем соц. сети и сайтом. Успешная авторизация через Логинзу ещё не даёт
авторизации на сайте. Обычно, для авторизации на сайте, пользователю необходимо ввести
верный логин и пароль, после чего он получает доступ. В нашем случае, успешная авторизация
через Логинзу — это своеобразный ввод логина и пароля, но ещё не авторизация.

Итак, имеем две таблицы в БД:
1. users (поля: user_id, nickname, password, email)
2. loginza (поля: id, identity, provider, nickname, email, status, user_id )

В первой таблице хранятся юзеры сайта, авторизация на сайте происходит именно по данным в
этой таблице. C полями этой таблицы, думаю, всё понятно.

Во второй таблице хранятся тоже юзеры. Но это юзеры, которые удачно авторизовались через
Логинзу.
identity — передаёт Логинза. Что-то типа уникального ключа у провайдера.
provider — передаёт Логинза. Это сервис, через который авторизовался юзер (вконтакт, фейсбук,
яндекс и тд)
nickname, email — предаёт Логинза. Ник (почта), который вернул провайдер авторизации. Может
быть что угодно. Или вообще не быть.
status — новый пользователь/старый пользователь
user_id — id юзера в таблце users

Это минимальный набор таблиц.

Сам скрипт авторизации


Страница авторизации

Полученный на первом этапе HTML код — это форма для входа. Размещается на странице
авторизации.

image

В полученом коде нужно указать адрес, по которому перейдёт пользователь в случае успешной
авторизации. Именно этот скрипт получит данные об авторизации!
loginza.ru/api/widget?overlay=loginza&token_url=вашсайтру/auth.php
Нужно указать полный URL-адрес с http:// или https://, предварительно кодированный PHP
функцией urlencode().
Скрипт приёма ответа и регистрации и авторизации юзера

Этот скрипт должен распознать ответ от логинзы и направить пользователя дальше.
Содержания скрипта примерно такое:
$loginzaid='ID'; //ID виджета мы получили в подготовительном этапе в интерфейсе кабинета
Логинзы.
$loginzakey='HASH'; //Ключ доступа мы получили в подготовительном этапе в интерфейсе
кабинета Логинзы.

$token=$_POST['token']; //Это вернула логинза.
$sig=md5($token.$loginzakey); //Формируем сигнатуру.
$kk="http://loginza.ru/api/authinfo?token=".$token."&id=".$loginzaid."&sig=".$sig.""; //формируем
url для получения ответа от Логинзы
$b=file_get_contents($kk); //Получаем данные от Логинзы
$authresult=json_decode($b,true); //Получаем PHP массив с данными авторизации


В массиве $authresult — данные об авторизированом пользователе.

В этом примере мы несколько упростим задачу и будем считать, что nickname и email переданы
провайдером авторизации и пользователя с такими даенными в нашей таблице юзеров ещё не
существует. На практике — надо это проверять, и если данных нет или они дублируют
существующий логин в базе юзеров — запрашивать уточнение у пользователя. Но это другая
история.


Итак, продолжаем.

Новый пользователь

Проверяем, не существует ли записи в таблице loginza с полученными параметрами provider и
identity
$res=mysql_query("SELECT * FROM $tbl_l WHERE identity='$authresult[identity]' AND
provider='$authresult[provider]'");

Если такой записи нет — то заносим пользователя в таблицу loginza
if(mysql_num_rows($res)==0)
{
mysql_query("INSERT INTO loginza (
`identity`,
`provider`,
`nickname`,
`email`,
`status`,
`soc_user_id`
)
VALUES
(
'$authresult[identity]',
'$authresult[provider]',
'$authresult[nickname]',
'$authresult[email]',
0,
0
)
") ;

}


Теперь точно этот пользователь есть.
Считаываем инфу о юзере с таким identity и provider (некрасиво, но для простоты
повествования).

$res=mysql_query("SELECT * FROM $tbl_l WHERE identity='$authresult[identity]' AND
provider='$authresult[provider]'");
$loginza=mysql_fetch_assoc($res);

Если это его первый вход и соотв. он ещё не зарегистрирован в таблице users — регистрируем его
там, а затем обновляем информацию таблице loginza:
if($loginza['status']==0)
{
$pwd=md5('сгенерировали пароль'); //сгенерировали (как угодно) и получили MD5-хеш пароля
mysql_query("INSERT INTO users (nickname, password, email) VALUES ('$loginza[nickname]',
'$pwd', '$loginza[email]' )"); //Внесли запись
$iid=mysql_insert_id(); //Получили ID созданной записи. Поле автоинкрементное.
// а теперь внесём информацию об этом в таблицу loginza
mysql_query("UPDATE loginza SET status=1, user_id=$iid WHERE id=$loginza[id]"); // поставили
статус=1 и ид юзера в основной базе users
}


Всё! Теперь у нас есть связь между авторизацией этого пользователя и Логинза.

Остаётся только авторизовать этого пользователя по таблице users и пустить на сайт.
if($loginza['status']==1)
{
Someauthorization($iid); //Авторизация, подробно не описываю
}


Существующий пользователь. Повторный вход.
Что же будет, если этот пользователь войдёт по новой (в следующий раз)? Вернёмся к моменту,
когда мы назначили проверку, на первый вход пользователя:
if($loginza['status']==0)

И так далее.
Если юзер уже входил успешно на сайт, status у него в таблице loginza равен единице.
Нам требуется узнать user_id этой loginza записи и отправить на авторизацию! И это всё!
if($loginza['status']==1)
{
Someauthorization($loginza['user_id']); //Авторизация, подробно не описываю
}

Пара слов о безопасности

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

Что же касается приведённого мною кода — это лишь пример, иллюстрация, а не готовый код. Не
стоит использовать приведённый мной код в том виде, в котором он есть.
Tags:
Hubs:
Total votes 12: ↑5 and ↓7-2
Comments12

Articles