I, krvss

  1. Навіщо Коли в нашому проекті виникла необхідність реалізувати авторизацію через соціальні мережі,...
  2. Що брати і на що звернути увагу

Навіщо

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

  1. Крім великих світових мереж хотілося також працювати з LiveJournal, Yandex та ВКонтакте.
  2. Потрібна була можливість контролювати дії системи після успішної авторизації, тобто управляти процесом обробки отриманої від сервісу інформації про користувачів.

Я зупинився на https://github.com/omab/django-social-auth : Переглянувши вихідні, я побачив, що їх небагато, а написано все зрозуміло. Спочатку бібліотека підтримувала Facebook, Twitter, Google, OpenID і OpenAuth і процес роботи з БД був трохи не такий, як хотілося б. ФОРКОМ було не уникнути, правда, незабаром ми з автором вихідної бібліотеки трохи подружилися, в результаті чого більша частина моїх змін пішла в основну гілку, а в моєму Форк залишилися тільки Yandex і ВКонтакте.

Після всіх змін результат мені припав дуже до вподоби: в разі потреби можна просто додавати движки для нових сервісів, а робота з БД досить проста, щоб не надто про неї думати. Також незалежно від того, як відбувається авторизація (о, іноді це досить складний процес, повірте мені на слово), робота з даними користувача уніфікована, що теж дуже зручно.

Як це працює

Для кожного сервісу є два класи - auth і backend. Безпосередньо ви з ними працюєте, тільки якщо вам потрібно додати свій сервіс, в іншому випадку ви просто викликаєте метод auth бібліотеки і згодовуєте йому ім'я сервісу і потрібні параметри. Після того як авторизація завершена, викликається метод complete. Що відбувається всередині, описано нижче.

1. Клас auth відповідає за авторизацію на сайті сервісу і переконується, що все пройшло успішно (див. Малюнок).

Малюнок)

2. Клас backend відповідає за авторизацію власне в вашому додатку (через стандартний authenticate) і за роботу з таблицею користувачів на підставі тих даних, якими сервіс зволив з вами поділитися. Деякі сервіси (не показуватимемо пальцем, хоча це був ЖЖ) не дають ніякої інформації, крім «наша людина / не наш чоловік».

Для backend можна задавати ту модель користувача, яка використовується у вашому додатку, якщо ви не використовуєте стандартний клас User. У менеджері цієї моделі можна, наприклад, приймати рішення, коли у google, а коли - використовувати вже наявного.

Для того щоб зрозуміти, чи потрібно оновлювати інформацію в таблиці користувачів, використовуючи дані, отримані з соціальної мережі (роблячи це на автоматі, ви ризикуєте привести користувача в лють, переписуючи дані в його профілі), в системі є спеціальний сигнал pre_update. Його ви можете обробити і відповісти, чи потрібно вносити зміни.

Його ви можете обробити і відповісти, чи потрібно вносити зміни

При успішній авторизації в спеціальній таблиці зберігається інформація про те, який користувач пов'язаний з якими (1: N) сервісами авторизації. Для прив'язки вже залогіненним користувача використовуються методи бібліотеки associate.

«Просто, зрозуміло, легко запам'ятати», як говорив капітан Д. Воробей.

Що брати і на що звернути увагу

Отже, мій форк тут: https://github.com/krvss/django-social-auth

В існуючу архітектуру досить легко вписався ВКонтакте - його backend зараз, крім авторизації, перевіряє також «підпис» даних, щоб чого не вийшло.

Коли ви, авторізуемся на Yandex через OpenId, ставите галочку «передати додаткові параметри», в Django чомусь виникає порушення цілісності або втрата csrf-інформації. Щоб не виникала помилка, можна вказати свою функцію для завершення авторизації (параметр SOCIAL_AUTH_COMPLETE_URL_NAME), яка буде відрізнятися тільки наявністю декоратора csrf_exempt_view і складатися з виклику social_auth.complete.

Upd: Причини такої поведінки Yandex пояснюються в коментарях до цього запису.