Авторизация в Laravel, через социальные сети (Ulogin). Просто, гибко и эффективно

в 14:33, , рубрики: api, laravel, laravel 5.3, mysql, php, PHP 7, ulogin, авторизация без паролей, Программирование, метки:

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

Я исхожу из того, что читатель разбирается во фреймворке Laravel 5.3 Поэтому я не буду разжевывать простые вещи. Итак, с чего начать? Для начала нам нужно на странице регистрации и авторизации подключить JS плагин. Лично я делаю это через создание отдельного шаблона auth/social.blade.php В который помещаю следующий простой код:

{{-- Social buttons--}}

<div class="text-center margin-bottom-20" id="uLogin"
     data-ulogin="display=panel;theme=flat;fields=first_name,last_name,email,nickname,photo,country;
                             providers=facebook,vkontakte,odnoklassniki,mailru;hidden=other;
                             redirect_uri={{ urlencode('http://' . $_SERVER['HTTP_HOST']) }}/ulogin;mobilebuttons=0;">
</div>

@section('js')
    <script src="//ulogin.ru/js/ulogin.js"></script>
@endsection

Немного объяснений к коду. urlencode используем для кодирования строки к нормальному для передачи по http виду. На redirect_uri будет приходить ответ от сервера Ulogin со статусами и данными. В поле fields мы указываем, какие данные нам нужно получить из социальной сети. В конце шаблона я подключаю сам плагин. Обратите внимание, что здесь происходит вставка кода в блок 'js', который должен быть прописан в главном шаблоне: yield('js')

Да, один момент. Если вы работаете по SSL, то вместо 'http://' указывайте 'https://'. Тогда не будет предупреждения о небезопасной передаче данных.

Когда шаблон готов, то мы его просто подключаем на странице регистрации и залогинивания в том месте, где нам нужно, просто вставив в шаблоне одну строчку: include('auth.social')

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

Теперь нам нужно написать бэкенд часть. А именно создать контроллер и роут. Роут будет получать ответ от сервера Ulogin и передавать его в наш контроллер.

Создаем контроллер с названием UloginController.php и прописываем в нем публичный метод login в который передаем запрос.

Создаем роут: Route::post('ulogin', 'UloginController@login');

Есть еще один нюанс! В Laravel есть защита от CSRF атак. А значит, передача данных с другого сервера не будет иметь токена безопасности и случится ошибка безопасности. Для того, чтобы это пофиксить, необходимо в посреднике (middleware) VerifyCsrfToken.php прописать исключение для нашего роута (пути): protected $except = ['ulogin'];

Теперь, когда сервер вернет ответ на '/ulogin', токен безопасности будет проигнорирован и ошибки не произойдет.

Теперь напишем сам контроллер:

<?php
/**
 * Ulogin.ru auto registration or login.
 */
namespace AppHttpControllers;

use AppUser;
use Auth;
use Hash;
use IlluminateHttpRequest;
use Redirect;

class UloginController extends Controller
{

// Login user through social network.
    public function login(Request $request)
    {
        // Get information about user.
        $data = file_get_contents('http://ulogin.ru/token.php?token=' . $_POST['token'] . '&host=' . $_SERVER['HTTP_HOST']);
        $user = json_decode($data, TRUE);

        $network = $user['network'];

        // Find user in DB.
        $userData = User::where('email', $user['email'])->first();

        // Check exist user.
        if (isset($userData->id)) {

            // Check user status.
            if ($userData->status) {

                // Make login user.
                Auth::loginUsingId($userData->id, TRUE);
            }
            // Wrong status.
            else {
                Session::flash('flash_message_error', trans('interface.AccountNotActive'));
            }

            return Redirect::back();
        }
        // Make registration new user.
        else {

            // Create new user in DB.
            $newUser = User::create([
                'nik' => $user['nickname'],
                'name' => $user['first_name'] . ' ' . $user['last_name'],
                'avatar' => $user['photo'],
                'country' => $user['country'],
                'email' => $user['email'],
                'password' => Hash::make(str_random(8)),
                'role' => 'user',
                'status' => TRUE,
                'ip' => $request->ip()
            ]);

            // Make login user.
            Auth::loginUsingId($newUser->id, TRUE);

            Session::flash('flash_message', trans('interface.ActivatedSuccess'));

            return Redirect::back();
        }
    }
}

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

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

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

Автор: Kirill_Dan

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js