Статьи

Социальные логины в PHP с HybridAuth

Тенденция на многих современных веб-сайтах — это функция, которая позволяет пользователям входить через свои учетные записи в социальных сетях. Классическим примером является сообщество SitePoint, где пользователи могут использовать свою учетную запись Facebook, Twitter, Google, Yahoo или GitHub для входа без необходимости регистрации учетной записи.

В этом уроке мы узнаем о HybridAuth — библиотеке PHP, которая избавляет от трудностей при создании функции входа в систему.

HybridAuth действует как абстрактный API между вашим приложением и различными социальными API и поставщиками удостоверений.

Установка

Рекомендуемый способ установки HybridAuth — через Composer. Мы также будем использовать Slim в качестве основы для нашего примера приложения.

{ "require": { "slim/slim": "2.*", "hybridauth/hybridauth": "2.3.0" } } 

Использование HybridAuth для социальных входов

Чтобы использовать HybridAuth, скопируйте файлы config.php и index.php (конечная точка HybridAuth) в /vendor/hybridauth/hybridauth/hybridauth в корневую папку вашего проекта.

Переименуйте файл index.php в hybrid.php потому что index.php будет использоваться платформой Slim для нашей логики демонстрационного приложения.

config.php файл config.php учетными данными вашего приложения (например, Facebook , Twitter ).

Например, если вы хотите, чтобы пользователи входили на ваш сайт через Facebook, Google и Twitter; ваш конфигурационный файл будет выглядеть примерно так URL моего приложения http://slim.local .

 return [ "base_url" => "http://slim.local/", "providers" => [ "Google" => [ "enabled" => true, "keys" => [ "id" => "", "secret" => "" ], ], "Facebook" => [ "enabled" => true, "keys" => [ "id" => "", "secret" => "" ], "trustForwarded" => false ], "Twitter" => [ "enabled" => true, "keys" => [ "key" => "", "secret" => "" ] ], ], "debug_mode" => true, "debug_file" => "bug.txt", ]; 

Примечание. Параметр base_url должен указывать на файл hybrid.php точки HybridAuth, который в нашем случае является hybrid.php .

Посмотрите Документацию Конфигурации HybridAuth для получения дополнительной информации.

Затем требуется автозагрузчик поставщика и создайте экземпляр класса.

 require 'vendor/autoload.php'; $hybridauth = new Hybrid_Auth( 'config.php' ); 

Используйте метод authenticate для аутентификации пользователей с данным провайдером.

Для Facebook:

 $adapter = $hybridauth->authenticate( "Facebook" ); 

Для Твиттера:

 $adapter = $hybridauth->authenticate( "Twitter" ); 

Для Google:

 $adapter = $hybridauth->authenticate( "Google" ); 

Параметр, который передается в authenticate() должен соответствовать ключу массива провайдера в файле config.php .

После аутентификации используйте метод getUserProfile() для получения данных профиля пользователя.

 $user_profile = $adapter->getUserProfile(); 

$user_profile будет объектом, который состоит из возвращенных данных профиля пользователя.

Больше социальных провайдеров

Чтобы добавить больше поставщиков к существующим, например GitHub, скопируйте файл GitHub.php из vendor/hybridauth/hybridauth/additional-providers/hybridauth-github/Providers в папку в вашем приложении (каталог provider в нашем случае). Используйте оболочку провайдера, чтобы загрузить файл, где path — это путь к файлу GitHub, и укажите имя класса PHP.

 "Github" => [ "enabled" => true, "keys" => [ "id" => "", "secret" => "" ], "wrapper" => [ "path" => "providers/GitHub.php", "class" => "Hybrid_Providers_GitHub" ] ] 

Аутентифицировать пользователя с помощью GitHub с помощью метода autheniticate() например:

 $adapter = $hybridauth->authenticate( "Github" ); 

Реализация социального входа

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

Одна из причин этой практики заключается в том, что Twitter, например, не возвращает адрес электронной почты аутентифицированного ими пользователя. То есть возвращенные данные профиля не содержат электронную почту пользователя.

Большинство (если не все) социальные провайдеры, такие как Facebook, Twitter, Google, LinkedIn и даже GitHub, включают уникальный идентификационный номер пользователя, возвращаемый после авторизации.

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

Кодирование демо-приложения

Мы будем создавать простое веб-приложение с использованием среды Slim PHP, чтобы продемонстрировать реальный пример того, как можно реализовать социальный вход в систему с помощью HybridAuth.

Я предполагаю, что у вас установлены HybridAuth и Slim Framework. В противном случае см. Руководство по установке выше.

Структура приложения

 |-scr/ |----App_Model.php |-templates/ |----login.php |----welcome.php |-vendor/ |-composer.json |-config.php |-hybrid.php |-index.php |-.htaccess 

Вот SQL для таблицы базы данных.

 CREATE TABLE IF NOT EXISTS `users` ( `id` int(10) NOT NULL AUTO_INCREMENT, PRIMARY KEY (id), `identifier` varchar(50) NOT NULL, UNIQUE KEY `identifier` (`identifier`), `email` varchar(50) DEFAULT NULL, `first_name` varchar(20) DEFAULT NULL, `last_name` varchar(20) DEFAULT NULL, `avatar_url` varchar(255) ) ENGINE=InnoDB; 

Кодирование модели приложения

Весь код для модели приложения должен App_Model.php файле App_Model.php в папке src .

Файл представляет собой пространство имен модели, за которым следуют определение класса и конструктор.

 <?php namespace Model; class App_Model { /** @var object Database connection */ private $conn; /** * Instantiate the model class. * * @param object $db_connection DB connection */ public function __construct(\PDO $db_connection) { $this->conn = $db_connection; } 

Метод identifier_exists возвращает значение true, если идентификатор (идентификационный номер пользователя) уже существует в базе данных, или значение false в противном случае.

 /** * Check if a HybridAuth identifier already exists in DB * * @param int $identifier * * @return bool */ public function identifier_exists($identifier) { try { $sql = 'SELECT identifier FROM users'; $query = $this->conn->query($sql); $result = $query->fetchAll(\PDO::FETCH_COLUMN, 0); return in_array($identifier, $result); } catch ( \PDOException $e ) { die( $e->getMessage() ); } } 

Метод register_user вставляет данные профиля пользователя в базу данных.

 /** * Save users record to the database. * * @param string $identifier user's unique identifier * @param string $email * @param string $first_name * @param string $last_name * @param string $avatar_url * * @return bool */ public function register_user( $identifier, $email, $first_name, $last_name, $avatar_url ) { try { $sql = "INSERT INTO users (identifier, email, first_name, last_name, avatar_url) VALUES (:identifier, :email, :first_name, :last_name, :avatar_url)"; $query = $this->conn->prepare($sql); $query->bindValue(':identifier', $identifier); $query->bindValue(':email', $email); $query->bindValue(':first_name', $first_name); $query->bindValue(':last_name', $last_name); $query->bindValue(':avatar_url', $avatar_url); return $query->execute(); } catch (\PDOException $e) { return $e->getMessage(); } } 

Метод login_user при вызове добавляет созданный сеанс пользователя в сеанс HybridAuth (созданный при успешной авторизации пользователя поставщиком).

 /** * Create user login session * * @param int $identifier */ public function login_user($identifier) { \Hybrid_Auth::storage()->set('user', $identifier); } 

Метод logout_user удаляет или уничтожает сеанс пользователя при нажатии на ссылку выхода из системы.

 /** Destroy user login session */ public function logout_user() { \Hybrid_Auth::storage()->set( 'user', null ); } 

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

 /** * Return user's first name. * * @param int $identifier * * @return string */ public function getFirstName( $identifier ) { if ( ! isset( $identifier )) { return; } $query = $this->conn->prepare( "SELECT first_name FROM users WHERE identifier = :identifier" ); $query->bindParam( ':identifier', $identifier ); $query->execute(); $result = $query->fetch( \PDO::FETCH_NUM ); return $result[0]; } /** * Return user's last name. * * @param int $identifier * * @return string */ public function getLastName( $identifier ) { if ( ! isset( $identifier )) { return; } $query = $this->conn->prepare( "SELECT last_name FROM users WHERE identifier = :identifier" ); $query->bindParam( ':identifier', $identifier ); $query->execute(); $result = $query->fetch( \PDO::FETCH_NUM ); return $result[0]; } /** * Return user's email address * * @param int $identifier * * @return string */ public function getEmail( $identifier ) { if ( ! isset( $identifier )) { return; } $query = $this->conn->prepare( "SELECT email FROM users WHERE identifier = :identifier" ); $query->bindParam( ':identifier', $identifier ); $query->execute(); $result = $query->fetch( \PDO::FETCH_NUM ); return $result[0]; } /** * Return the URL of user's avatar * * @param int $identifier * * @return string */ public function getAvatarUrl( $identifier ) { if ( ! isset( $identifier )) { return; } $query = $this->conn->prepare( "SELECT avatar_url FROM users WHERE identifier = :identifier" ); $query->bindParam( ':identifier', $identifier ); $query->execute(); $result = $query->fetch( \PDO::FETCH_NUM ); return $result[0]; } 

Зарегистрируйте автозагрузчик PSR-4 для класса Model, добавив приведенный ниже код в файл composer.json.

 "autoload": { "psr-4": {"Model\\": "src/"} } 

Запустите composer dump-autoload чтобы заново сгенерировать файл vendor/autoload.php .

Логика приложения

Требуйте файл автозагрузки композитора и создайте экземпляр Slim в файле приложения index.php .

 require 'vendor/autoload.php'; $app = new \Slim\Slim(); 

Каталог с именем templates для хранения всех наших файлов шаблонов создается, а затем регистрируется или настраивается в Slim следующим образом:

 $app->config( [ 'templates.path' => 'templates' ] ); 

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

 // Set singleton value $app->container->singleton( 'db', function () { try { $db = new PDO( 'mysql:host=localhost;dbname=hybridauth', 'slim', 'slim', [ \PDO::ATTR_PERSISTENT => false ] ); } catch ( PDOException $e ) { die( 'Error!: ' . $e->getMessage() ); } return $db; } ); 

Также создается другой одноэлементный ресурс, который возвращает экземпляр HybridAuth.

 $app->container->singleton( 'hybridInstance', function () { $instance = new Hybrid_Auth('config.php'); return $instance; } ); 

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

 $model = new \Model\App_Model( $app->db ); 

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

 $authenticate = function ( $app ) { return function () use ( $app ) { $app->hybridInstance; $session_identifier = Hybrid_Auth::storage()->get( 'user' ); if (is_null( $session_identifier ) && $app->request()->getPathInfo() != '/login/') { $app->redirect( '/login/' ); } }; }; 

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

 $app->get( '/', $authenticate($app) ); 

Ниже приведено определение маршрута ссылок для входа в систему. Т.е. при нажатии ссылки http: //slim.local/login/facebook пользователь перенаправляется на Facebook с помощью HybridAuth для авторизации. То же самое касается Твиттера http: //slim.local/login/twitter , Google http: //slim.local/login/google и всех других поддерживаемых поставщиков.

 $app->get( '/login/:idp', function ( $idp ) use ( $app, $model ) { try { $adapter = $app->hybridInstance->authenticate( ucwords( $idp ) ); $user_profile = $adapter->getUserProfile(); if (empty( $user_profile )) { $app->redirect( '/login/?err=1' ); } $identifier = $user_profile->identifier; if ($model->identifier_exists( $identifier )) { $model->login_user( $identifier ); $app->redirect( '/welcome/' ); } else { $register = $model->register_user( $identifier, $user_profile->email, $user_profile->firstName, $user_profile->lastName, $user_profile->photoURL ); if ($register) { $model->login_user( $identifier ); $app->redirect( '/welcome/' ); } } } catch ( Exception $e ) { echo $e->getMessage(); } } ); 

Метод HybridAuth authenticate() вызывается, чтобы перенаправить пользователя к данному социальному провайдеру.

При успешной авторизации переменная $user_profile заполняется данными профиля пользователя.

Метод identifier_exists() вызывается, чтобы проверить, существует ли идентификатор пользователя в базе данных. Если это правда, пользователь заходит на сайт. В противном случае для пользователя создается учетная запись, после чего пользователь входит в систему.

Вот код для маршрута выхода.

 $app->get( '/logout/', function () use ( $app, $model ) { $app->hybridInstance; $model->logout_user(); Hybrid_Auth::logoutAllProviders(); $app->redirect( '/login/' ); } ); 

Метод logout_user мы говорили в классе модели, вызывается для уничтожения пользовательского сеанса, а Hybrid_Auth::logoutAllProviders() также вызывается для выхода пользователя из подключенного провайдера.

Маршрут страницы приветствия, на которую перенаправляются пользователи при входе в систему:

 $app->get( '/welcome/', $authenticate( $app ), function () use ( $app, $model ) { $app->render( 'welcome.php', [ 'model' => $model ] ); } ); 

Наконец, запустите приложение Slim.

 // app/index.php $app->run(); 

Смотрите репозиторий GitHub приложения для полного исходного кода.

Вывод

В этой статье мы узнали, как интегрировать функцию социального входа в систему с веб-сайтом с помощью мощной и надежной библиотеки HybridAuth PHP.

Если у вас есть какие-либо вопросы или предложения, сообщите нам об этом в комментариях.