Рубріки: Back-endОпыт

Моя история с Laravel, MongoDB и выдачей токена для API: как я научилась решать непростые задачи

Тетяна Козельська

Привет! Меня зовут Таня Козельская и я Full-Stack Developer с семилетним опытом. Сейчас работаю в компании Grid Dynamics. Если вы когда-нибудь, как и я, выбрали или собираетесь выбрать композицию для своего проекта, состоящую из фреймворка Laravel, базы MongoDB и при этом вам нужно выдавать токен для АРI эта статья может пригодиться. 

Как появилась проблема

Немного общей сухой информации. Ну, на всякий случай.

Laravel  это бесплатный веб-фреймворк PHP с открытым кодом, предназначенный для разработки веб-приложений, следующих по архитектурной схеме модели-просмотра (MVC) и основанный на Symfony. 

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

Итак, начну рассказ с моего опыта работы. В недалеком 2018 году для одного из своих проектов я выбрала именно такой набор. Поначалу все было отлично, ведь в Laravel есть интегрированный в структуру компонент Passport, который позволяет легко аутентифицировать пользователя, выдавать токен, контролировать время сессии и так далее.

Но оказалось, что есть маленькая проблемка, и по умолчанию Laravel не умеет работать, используя Passport и MongoDB.

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

Специальная библиотека на GitHub

Название библиотеки — designmynight/laravel-mongodb-passport. Если найдете ее на GitHub, то там все очень просто и подробно описано: 

  • устанавливаем зависимость через composer;
  • указываем в модели пользователя использование библиотеки, а не стандартное расширение для работы с базой;
  • добавляем библиотеку в файл конфигурации провайдеров.

На этом все, дальше можем использовать функцию createToken. Все работает достаточно стабильно. Но есть один момент — эта полезная библиотека зависит от многих других зависимостей в composerфайле. И пока Laravel не обновилась до версии 7, все было хорошо. А после обновления использования этой библиотеки стало просто невозможным.

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

Сначала я отслеживала репозиторий библиотеки и думала: «Ну, окей, у меня Laravel 6, а получилось только еще одно обновление, можно подождать». Возможно, все будет хорошо и библиотека начнет поддерживать обновление. Между тем на GitHub появляется все больше и больше комментариев о необходимом обновлении, и я одна из тех разработчиц, которые ждут апдейта.

Появляется fork от основной бранчи с комментарием: «Хэй, гайз, все работает для новой версии». Я, конечно, пробую это обновление со странными махинациями при обновлении composerфайла.

Все это выглядело так, будто я пытаюсь обмануть зависимости и каким-то чудом получить завершение работы команды composer update

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

Новое расширение Laravel Sanctum

Вышла Laravel 8, а обновления библиотеки так и не произошло. Я отставала уже на две версии фреймворка. Я получила время и разрешение от клиента на эксперименты и начала искать выход самостоятельно, исследуя недра фреймворка и Passport. 

Мое внимание было направлено на новое расширение Laravel Sanctum, появившееся с 7-й версии. По информации, указанной в документации, с его помощью можно создать легкую систему проверки подлинности для SPA (одностраничных приложений), мобильных приложений и простых API на основе токенов. Это выглядело как нужная мне деталь для приложения. Но и здесь я столкнулась с тем же — использованием MongoDB.

Мой опыт с MongoDB

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

Итак, пошагово это выглядит так:

1. Выполняем базовые команды, указанные в документации Laravel Sanctum для composer:

composer require laravel/sanctum

2. Паблишим провайдер-файл, который позже мы заменим на собственный:

php artisan vendor:publish --provider="LaravelSanctumSanctumServiceProvider"

3. В модели пользователя подключаем все необходимое для работы Sanctum:

use AppsanctumHasApiTokens;
use AppAuthUser as Authenticatable;

Для моей модели это вот эти два файла и при этом модель должна подражать и юзать эти классы:

class User extends Authenticatable implements CanResetPasswordContract
{
   use  Notifiable, CanResetPassword, HasApiTokens;

Думаю, что из третьего пункта уже ясно, что нужно создать свою директорию для Sanctum, в которой будет еще много файлов. Также нам необходим файл AuthUser.php

4. Файл AuthUser.phpсодержит весь базовый код из ядра Laravel Sanctum, но для нас важно то, что мы указываем здесь модуль для работы с базой MongoDB:

use JenssegersMongodbEloquentModel as Model;
<?php
namespace App;
use IlluminateAuthAuthenticatable;
use IlluminateAuthMustVerifyEmail;
use IlluminateAuthPasswordsCanResetPassword;
use IlluminateContractsAuthAccessAuthorizable as AuthorizableContract;
use IlluminateContractsAuthAuthenticatable as AuthenticatableContract;
use IlluminateContractsAuthCanResetPassword as CanResetPasswordContract;
use JenssegersMongodbEloquentModel as Model;
use IlluminateFoundationAuthAccessAuthorizable;
class AuthUser extends Model implements
   AuthenticatableContract,
   AuthorizableContract,
   CanResetPasswordContract
{
   use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}

5. Далее в директорию sanctum нужно поместить следующие файлы:

Эти файлы нужны, поскольку каждый из них вызывает другой, и если не изменить использование на кастомный файл, использующий монгу, то ничего не получится. Начинку этих файлов можно взять из базовой структуры фреймворка и ничего не менять, кроме namespace. У меня это: Appsanctum;.

Исключение — файл PersonalAccessToken.php. В нем нам также следует указать использование MongoDB.

6. Итак, здесь мы подключаем нужный класс для PersonalAccessToken.php:

<?php
namespace Appsanctum;
use JenssegersMongodbEloquentModel;
use LaravelSanctumContractsHasAbilities;
class PersonalAccessToken extends Model implements HasAbilities
{

 7. Если вы заметили, то в директории Sanctum есть файл SanctumServiceProvider.php, именно на него нужно изменить в файле configapp.php базовый провайдер для Sanctum.

Создание и передача токена

На этом настройка и подготовка заканчиваются и можно спокойно использовать способ createToken для создания и передачи токена пользователю по АРI. У меня это выглядит так: 

$user->createToken('app_name', base64_encode($user->_id))->plainTextToken;

Готово!

Надеюсь, мой опыт был интересен и полезен вам. Удачи! 

Читайте также: Мастер на все руки: дорожная карта фулстек-разработчика на 2022 год

If you have found a spelling error, please, notify us by selecting that text and pressing Ctrl+Enter.

Останні статті

Токсичные коллеги. Как не стать одним из них и прекратить ныть

В благословенные офисные времена, когда не было большой войны и коронавируса, люди гораздо больше общались…

07.12.2023

Делать что-то впервые всегда очень трудно. Две истории о начале карьеры PM

Вот две истории из собственного опыта, с тех пор, когда только начинал делать свою карьеру…

04.12.2023

«Тыжпрограммист». Как люди не из ІТ-отрасли обесценивают профессию

«Ты же программист». За свою жизнь я много раз слышал эту фразу. От всех. Кто…

15.11.2023

Почему чат GitHub Copilot лучше для разработчиков, чем ChatGPT

Отличные новости! Если вы пропустили, GitHub Copilot — это уже не отдельный продукт, а набор…

13.11.2023

Как мы используем ИИ и Low-Code технологии для разработки IT-продукта

Несколько месяцев назад мы с командой Promodo (агентство инвестировало в продукт более $100 000) запустили…

07.11.2023

Университет или курсы. Что лучше для получения IT-образования

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

19.10.2023