- PVSM.RU - https://www.pvsm.ru -
В конце прошлого лета я задумался над простым способом авторизации пользователей форума в мобильном приложении. Как раз в это время вышла версия Laravel 5.3 вместе с пакетом Laravel Passport, где подобное предлагалось из коробки. Раньше я не работал с OAuth 2, так что начал не спеша разбираться. Решил испытать механизм на крысах, в небольшой игре на Unity про Крысу на Стене. Сама игра — простейший раннер, но механизм авторизации может представлять некоторый интерес, если ранее не сталкивался с этим. Я пользовался официальной документацией [1] и статьей про Passport [2]. На хабре подходящей статьи до сих пор не появилось, поэтому решил сам скомпоновать материал, реализовав для интереса добавление рекордов и базовое взаимодействие с клиентом на Unity. Ввиду моей неторопливости это растянулось почти на год, так что сейчас в примерах используются уже Laravel 5.5 и Unity 2017.1.
В первой части статьи разберёмся, как с помощью токена авторизации добавить рекорд пользователя на сайт.
composer global require "laravel/installer"
laravel new <название проекта>
laravel new ratwall-laravel
Дальнейшие команды выполняем из созданной директории. Заходим туда
cd ratwall-laravel
.env
прописываем данные для подключения к базе данных. В этом гайде мы будем работать с SQLite, пропишем
DB_CONNECTION=sqlite
DB_DATABASE=/полный/путь/к/папке/проекта/database/database.sqlite
После этого создадим соответствующий пустой файл (командой touch database/database.sqlite
из консоли или, в случае Windows, из любого редактора файл database.sqlite
в директории database
)
php artisan serve
Он будет доступен по адресу http://127.0.0.1:8000/ [5]
php artisan make:auth
composer require laravel/passport
config/app.php
необходимо было зарегистрировать соответствующий сервис-провайдер. Для этого в массив providers
добавляем строку
LaravelPassportPassportServiceProvider::class,
Если вы устанавливаете Laravel 5.5 (текущая на момент публикации статьи) или выше — этот пункт можно пропустить.
php artisan migrate
php artisan passport:install
Установщик создаст пару ключей, в дальнейшем мы будем работать с ключом типа Password grant client, так что можно сразу записать ключ для Client ID = 2.
AppUser
трейт LaravelPassportHasApiTokens
с методами Passport. Класс будет выглядеть так:
<?php
namespace App;
use IlluminateNotificationsNotifiable;
use IlluminateFoundationAuthUser as Authenticatable;
use LaravelPassportHasApiTokens;
class User extends Authenticatable
{
use Notifiable, HasApiTokens;
// ...
// оригинальный код
// ...
}
Passport::routes
в загрузочный метод (boot
) сервис-провайдераAppProvidersAuthServiceProvider
. Сервис-провайдер будет выглядеть следующим образом:
<?php
namespace AppProviders;
use IlluminateSupportFacadesGate;
use IlluminateFoundationSupportProvidersAuthServiceProvider as ServiceProvider;
use LaravelPassportPassport;
class AuthServiceProvider extends ServiceProvider
{
// ...
// оригинальный код
// ...
public function boot()
{
$this->registerPolicies();
Passport::routes();
}
}
config/auth.php
устанавливаем драйвер у гарда api
как passport
.
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'passport',
'provider' => 'users',
],
],
Есть несколько способов авторизации через Passport. Мы рассмотрим простейший способ авторизации через логин-пароль, посредством Password Grant Token. Этот способ позволяет пользователю заполнить форму авторизации прямо в вашем приложении. При установке Laravel Passport один клиент для этого способа авторизации уже был создан (Password grand client, Client ID = 2), можно использовать его. Для создании нового нужно запустить
php artisan passport:client --password
Введите название для клиента, чтобы завершить создание.
Команда выведет Client ID и Client Secret. Запомните их, они понадобятся и в этой статье, и в следующей, при формировании запроса от клиента игры.
Создадим модель для будущих рекордов. Ключ -m
означает, что будет также создана соответствующая миграция. При добавлении ключа -c
также будет создан контроллер, но в нашем упрощенном случае это не нужно.
php artisan make:model Record -m
После создании модели нужно подготовить миграцию. Отредактируем файл database/migrations/<дата>_create_records_table.php
. По-умолчанию у миграции прописано создание поля id
(для первичного ключа) и сразу два поля для сохранения времени создания и редактирования записи (timestaps
). Для простейшего хранения данных о рекордах добавим два числовых поля — score
(значение рекорда) и user_id
(идентификатор пользователя, поставившего рекорд). После этого миграция будет выглядеть следующим образом:
<?php
use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;
class CreateRecordsTable extends Migration
{
public function up()
{
Schema::create('records', function (Blueprint $table) {
$table->increments('id');
// Значение рекорда - только положительное
$table->integer('score')->unsigned();
// Идентификатор пользователя - поле может быть пустым
$table->integer('user_id')->unsigned()->nullable();
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('records');
}
}
Импортируем в БД с помощью команды
php artisan migrate
Отредактируем саму модель AppRecord
. Добавим метод user()
для связи с моделью пользователя по полю user_id
.
<?php
namespace App;
use IlluminateDatabaseEloquentModel;
class Record extends Model
{
// Пользователь
public function user()
{
return $this->belongsTo(User::class);
}
}
Для добавления рекорда в базу создадим два роута для API, практически одинаковых, но один из них предназначен для добавления рекорда анонимным пользователем, а другой — авторизированным. В этом туториале мы не будем писать отдельный контроллер для рекордов, всю обработку вынесем в анонимную функцию роута. Для этого в файл routes/api.php
добавим:
Route::post('/anonymrecord', function (Request $request) {
// Создаем новую запись рекорда
$record = new AppRecord();
// Добавляем результат
$record->score = $request->get('score');
// Сохраняем запись
$record->save();
// Возвращаем сообщение
return response()->json([
'message' => 'Рекорд добавлен!',
], 201);
});
Route::middleware('auth:api')->post('/record', function (Request $request) {
// Создаем новую запись рекорда
$record = new AppRecord();
// Добавляем результат
$record->score = $request->get('score');
// Если запись добавил авторизированный пользователь, указываем его
$record->user_id = Auth::id();
// Сохраняем запись
$record->save();
// Возвращаем сообщение
return response()->json([
'message' => 'Пользователь '. Auth::user()->name .' добавил рекорд!',
], 201);
});
Здесь мы передаем рекорд в POST-запросе, добавляем его в базу и возвращаем сообщение об успехе. Мы добавили два практически идентичных роута — первый для анонимного добавления, второй для добавления рекорда авторизированным пользователем. Авторизированный пользователь может воспользоваться и анонимным роутом, но в нем не будет корректно обрабатываться информация о пользователе, поэтому в качестве варианта решения мы и разделили роуты. При вызове второго роута анонимным пользователем вас будет перенаправлять на форму авторизации.
В этом файле уже был один роут — user
, для получения информации об авторизированном пользователе. Мы ещё вернемся к нему позже.
Можно проверить работоспособность запроса для добавления анонимного рекорда с помощью http-клиента типа Postman (в дальнейшем примеры именно с ним), передав POST-запрос с заданным числовым значением score в форме по адресу http://127.0.0.1:8000/api/anonymrecord [6]. В ответ мы получим json
с сообщением, что рекорд добавлен.
Для отображения добавленных рекордов на сайте напишем роут в routes/web.php
с запросом всех рекордов из базы. Он использует шаблон records.blade.php
, которое мы создадим в следующем шаге.
Route::get('/records', function () {
$records = AppRecord::all();
return view('records', compact('records'));
});
Создадим шаблон resources/views/records.blade.php
для отображения таблицы рекордов.
@extends('layouts.app')
@section('content')
<div class="container">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<div class="panel panel-default">
<div class="panel-heading">Рекорды</div>
<div class="panel-body">
<table class="table table-striped table-hover">
<tr>
<th>Пользователь</th>
<th>Рекорд</th>
<th>Дата</th>
</tr>
@foreach ($records as $record)
<tr>
<td>{{ $record->user ? $record->user->name : 'Аноним' }}</td>
<td>{{ $record->score }}</td>
<td>{{ $record->created_at->diffForHumans() }}</td>
</tr>
@endforeach
</table>
</div>
</div>
</div>
</div>
</div>
@endsection
Если рекорд добавил авторизированный пользователь, выводим его имя, иначе — Аноним.
Теперь по адресу http://127.0.0.1:8000/records [7] нам доступна таблица рекордов — пустая или с теми записями, что мы добавили через Postman.
Эти рекорды добавлялись от Анонима, т.к. мы обращались к роуту анонимного добавления, а не к роуту авторизированного пользователя с токеном авторизации через Postman. Займемся вторым случаем.
Зарегистрируемся на сайте, используя стандартный механизм Laravel, перейдя по адресу http://127.0.0.1:8000/register [8]. Для примера я указал e-mail habr@habrahabr.ru, пароль habrahabr, имя Habr.
Для того, чтобы получить токен авторизации через Password Grant Token, нужно отправить POST-запрос на адрес http://127.0.0.1:8000/oauth/token [9]. В тело запроса нужно добавить следующие данные:
grant_type
— указываем тип password, т.к. мы используем Password Grant Token;client_id
— идентификатор Client ID из раздела Password Grant Token;client_secret
— ключ Client Secret, из раздела Password Grant Token;username
— в качестве логина для авторизации в базовом функционале Laravel используется e-mail;password
— пароль,scope
— области применения токена (для задания разрешений), оставим *, т.е. все.Отправим такой запрос через Postman. Если всё заполнено правильно, в ответ мы получим токен обновления, токен авторизации, время действия токена в секундах и тип токена — Bearer. Нам нужен токен авторизации — Access Token.
Проверим токен в действии, получив по нему информации об авторизированном пользователе. Выполним новый POST-запрос через Postman по адресу http://127.0.0.1:8000/api/user [10]. При этом в раздел Headers нового запроса нужно добавить ключ Authorization
со значением Bearer <токен авторизации>
(то есть тип токена, пробел, сам токен). В результате мы получим информацию о пользователе, которому соответствует этот токен авторизации.
Теперь можно выполнить POST-запрос для добавления рекорда авторизированным пользователем через Postman. Заполним Headers нового POST-запроса аналогично последнему, в качестве адреса используем http://127.0.0.1:8000/api/record [11]. В ответном сообщении теперь отображается имя пользователя, которое соответствует переданному токену.
Если зайти на страницу рекордов, можно увидеть, что у последнего добавленного рекорда стоит имя пользователя.
В следующей части будем работать с нашим небольшим API уже из Unity.
Готовый проект можно скачать на гитхабе [12].
Автор: KuzyT
Источник [13]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/php-2/265877
Ссылки в тексте:
[1] официальной документацией: https://laravel.com/docs/master/passport
[2] статьей про Passport: https://mattstauffer.com/blog/introducing-laravel-passport/
[3] установщик Laravel: https://laravel.com/docs/master/installation
[4] Composer: https://getcomposer.org/
[5] http://127.0.0.1:8000/: http://127.0.0.1:8000/
[6] http://127.0.0.1:8000/api/anonymrecord: http://127.0.0.1:8000/api/anonymrecord
[7] http://127.0.0.1:8000/records: http://127.0.0.1:8000/records
[8] http://127.0.0.1:8000/register: http://127.0.0.1:8000/register
[9] http://127.0.0.1:8000/oauth/token: http://127.0.0.1:8000/oauth/token
[10] http://127.0.0.1:8000/api/user: http://127.0.0.1:8000/api/user
[11] http://127.0.0.1:8000/api/record: http://127.0.0.1:8000/api/record
[12] гитхабе: https://github.com/KuzyT/ratwall-laravel
[13] Источник: https://habrahabr.ru/post/340282/?utm_source=habrahabr&utm_medium=rss&utm_campaign=sandbox
Нажмите здесь для печати.