Pull to refresh

Размышления о привязке «Войти через...» к одному аккаунту

Reading time 5 min
Views 19K
Постановка проблемы

Некоторое время назад по долгу службы работы, встал на обсуждение вопрос «А нужно ли делать на новом проекте авторизацию через сторонние сервисы?». Мозг, взбудораженный красивыми всплывающими окошками, виджетами и прочими украшательствами, призывно требующими «Войди через меня!», конечно же обеими руками был за, да и современные вебдванольные (а то и, тьфу тьфу, вебтринольные, быть может?) тенденции развития крупных порталов, как бы, намекают. Однако, я не зря сказал, что началось всё с обсуждения, ибо, где есть споры, там есть и камни преткновения. Такой камень мы нашли и здесь.

Предположим, на сайте имеется красивая панелька, как, например, у логинзы, или просто отдельные виджеты авторизации, например, через контакт, твиттер, фейсбук и иже с ними. Легко войти на сайт? Безусловно. Но при этом, если человек войдет сразу со всех этих аккаунтов (одновременно или нет, не суть), для системы это будут разные люди, а следовательно, клоны одного и того же человека, учётной записи которого, быть может, и вовсе нету на сайте.

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

А вот тут всё зависит от сути нашего проекта. Если у нас весьма узконаправленный сайт, на котором, например, можно читать какие-либо новости и гадписать в комментах, мы можем удовлетвориться и внешними сервисами. А если каждый пользователь на сайте — это целый мир, со своими статьями, объявлениями, рейтингами, вино-водочными заводами и аэрокосмическими шаттлами?

Звездные воины — атака клонов


Сразу предупреждаю, данная статья носит пока только чисто теоретический характер, и создана с целью послушать идеи и предложения всех решивших прочитать ее хаброжителей.

Поиски решения проблемы

Бегло пробежавшись по имеющимся в наличии ресурсам и изучив API самых распространенных сервисов, было выяснено (не в смысле, «Ух ты, блин! А я и не знал!», а в смысле «Ага… И здесь вот так, и здесь, и даже здесь тоже»), что все они работают по одному и тому же принципу.

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

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

Приготовления

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

Итак, для начала, нам понадобятся три таблицы в базе данных.

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

— ID пользователя
— Логин (или любое другое поле, уникальное, выступающее в качестве логина)
— Пароль (шифрованный или нет, решайте сами)

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

— ID ресурса
— Название ресурса (например, «Вконтакте»)
— Машинное имя ресурса (например, «vkontakte»)
— Место идентификатора пользователя в ссылке (например, «vkontakte.ru/{ID}» )
— Ключ (ID) приложения (в нашем случае, нашего сайта) на этом ресурсе

И третья таблица, и, пожалуй, самая главная, это "Связи", которая будет включать в себя соответствия аккаунта пользователя на нашем сайте аккаунту на внешнем ресурсе. Она выглядит так:
— ID связи (классика, да?)
— ID ресурса
— ID пользователя на нашем сайте
— ID (или идентификатор) пользователя на внешнем ресурсе

Так же, в дальнейшем, для каждого из ресурсов, предоставленных на нашем сайте, у нас должны быть соответствующие представления (какие-то popup-окошки и другие чудеса), которые будут выводить тот или иной виджет, а так же функции (классы, хелперы, модули или что угодно) что будет высчитывать и проверять соответствующий API ключ, но об этом дальше.

Немного алгоритмов

Итак, теперь само действие. Начнем с самого легкого!

Предположим, у нас есть сайт, на котором мы видим форму традиционного входа/регистрации, а так же панельку с некоторыми виджетами некоторых внешних ресурсов.

Когда человек входит/регистрируется на нашем сайте традиционно, пройдя заключительную процедуру авторизации, он попадет на наш сайт или сразу в свою панель, где увидит раздел настроек. Зайдя в этот самый раздел, он увидит там панель, например, «Профили на внешних ресурсах», где будут созданные в нашей таблице внешних ресурсов поля.

Предположим, пользователь выбрал поле «Вконтакте», и ввел туда свой идентификатор. Как запустится процесс — при потере фокуса инпута, или при нажатии кнопки, или благодаря НЛО — нам не важно, важны последствия. Мы запускаем соответствующую процедуру авторизации соответствующего виджета (всплывающее окошно, ajax-запрос на нужный скрипт или еще что-то).

Если пользователь уже авторизован на внешнем ресурсе, нам вернутся необходимые данные, в противном случае, пользователь должен будет авторизоваться, и нам всё же придут долгожданные данные. И вот тут начинается колдунство.

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

Если два ключа совпадают, а так же совпадает введенный идентификатор с полученным в открытую, значит, перед нами действительно обладатель указанной учетной записи. В таком случае, мы создаем строку в таблице "Связи", и введенный идентификатор становится уникальным, больше никто не сможет ввести такой же (как вариант, в случае попытки ввода, показывать ошибку, что кто-то под таким ID уже есть, и выводить ссылку на этого человека).

В случае же, когда ключи не совпали, стоит поругать человека за попытку похитить чей-то идентификатор, или вежливо переспросить, вошел ли он под своей учёткой, или по привычке залез на страницу своей девушки/парня.

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

Самый простой вариант закончили. Переходим к самому сложному — авторизация через внешку без регистрации на сайте.

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

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

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

Выводы

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

К сожалению, в данный момент у меня нет времени заниматься реализацией вышеописанного алгоритма, но если я буду делать его, но в первую очередь под фреймворк Kohana, посему сейчас я буду рад выслушать конструктивную критику и предложения, как и что здесь можно улучшить. Спасибо за внимание
Tags:
Hubs:
+66
Comments 218
Comments Comments 218

Articles