Веб-проекты (Часть II): Система авторизации Laravel/Nuxt

Веб-проекты (Часть II): Система авторизации Laravel/Nuxt

MetaTrader 5Интеграция | 14 февраля 2022, 16:36
3 640 12
Anatoli Kazharski
Anatoli Kazharski

Содержание


1. Введение

В статье Веб-проекты (Часть I): Создание веб-приложения в схеме Laravel/Nuxt/MetaTrader 5 мы рассматривали такие вопросы, как:

  • Подготовка окружения для веб-разработки в Windows и Ubuntu.
  • Создание проекта в связке фреймворков Laravel и Nuxt.
  • Работа с системой контроля версий Git

В этой статье создадим систему авторизации через браузерное приложение и через торговый терминал MetaTrader 5. Можно будет зарегистрироваться в системе, указав свои учётные данные. Для тех, кто только начинает разбираться в настройке систем авторизации эта тема может показаться довольно сложной. Поэтому в этой статье изложение материала будет достаточно подробным, чтобы можно было последовательно и без ошибок всё повторить у себя и понять принцип разработки и настройки подобных систем. Всё упрощается тем, что для фреймворков Laravel и Nuxt уже есть готовые пакеты для различных видов систем авторизации. Что касается MetaTrader 5/MQL5, то методы для авторизации пользователей будут реализованы и представлены во второй главе, так как объём материала не позволяет всё опубликовать в одной статье. 

Кроме этого, кратко пройдёмся по вопросам касающихся работы с фреймворками Laravel и Nuxt. Будут рассмотрены такие темы, как:

  • Маршруты для авторизации.
  • Именованные ограничители запросов.
  • Отправка и валидация запросов.
  • Переменные окружения и файлы конфигурации.
  • Миграции базы данных в Laravel.
  • Тестирование запросов в Postman.
  • Работа с заголовками в HTTP-запросах и ответах сервера.

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


2. Подключение к базе данных

В предыдущей статье для Windows 10 мы рассматривали установку комплекса инструментов Laragon, среди которых есть менеджер управления базами данных HeidiSQL. Тогда же через это приложение мы создали сеанс и базу данных. Теперь нужно настроить переменные окружения Laravel для подключения к базе данных. Для этого откройте файл .env в проекте Laravel и найдите переменные, которые показаны в листинге ниже. Установите значения в соответствии с тем, какие устанавливали при создании базы данных.

...

DB_CONNECTION =mysql
DB_HOST       =127.0.0.1
DB_PORT       =3306
DB_DATABASE   =mql5
DB_USERNAME   =root
DB_PASSWORD   =

...


3. Система аутентификации Laravel Sanctum

Самый простой вариант для реализации системы авторизации предоставляется в Laravel 8 сразу же во время создания проекта. Если используется другая версия и в ней это не заложено изначально, то тогда следуйте инструкции в документации Laravel. Здесь же будет краткое описание с учётом того, что этот пакет уже установлен.

3.1. Файл composer.json

В файле composer.json в списке зависимостей (установленных пакетов) Вы можете увидеть его под названием laravel/sanctum в разделе require.

{
    "name": "laravel/laravel",
    "type": "project",
    "description": "The Laravel Framework.",
    "keywords": ["framework", "laravel"],
    "license": "MIT",
    "require": {
        "php": "^7.3|^8.0",
        "fruitcake/laravel-cors": "^2.0",
        "guzzlehttp/guzzle": "^7.0.1",
        "laravel/framework": "^8.75",
        "laravel/sanctum": "^2.11",
        "laravel/tinker": "^2.5"
    },
    "require-dev": {
        "facade/ignition": "^2.5",
        "fakerphp/faker": "^1.9.1",
        "laravel/sail": "^1.0.1",
        "mockery/mockery": "^1.4.4",
        "nunomaduro/collision": "^5.10",
        "phpunit/phpunit": "^9.5.10"
    },
    ...
}

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

Когда Вы клонируете репозиторий с GitHub для разработки, то для установки всех пакетов (require и require-dev) Вам нужно запустить команду:

composer install

Если Вы публикуете сайт в интернете и Вам не нужны пакеты из раздела require-dev, то тогда нужно запустить эту же команду с параметром --no-dev:

composer install --no-dev

3.2. Файлы конфигурации

Обратите также внимание на настройки в файлах config\cors.php и config\sanctum.php. Первый создаётся в проекте при установке пакета fruitcake/laravel-cors (см. в листинге предыдущего раздела) и предназначен для настройки взаимного обмена ресурсами (CORS). На данном этапе в файле config\cors.php в параметре paths указаны пути, для которых включена служба CORS. Все они начинаются с префикса api/. По умолчанию любые источники (*) могут обращаться по этим адресам. Кроме этого, параметру supports_credentials нужно установить значение true, что означает: включить учётные данные пользователя в запросах. Позже мы ещё вернёмся к этим настройкам, а пока всё можно оставить, как есть.

<?php

return [
    'paths' => ['api/*'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,
];

В конфигурационном файле config\sanctum.php в параметре stateful содержится массив доменов, с которых могут осуществляться запросы для получения куков аутентификации API. Как правило, здесь указываются локальный и производственный домены, которые получают доступ к API через фронтенд SPA. Удобнее будет вынести переменную SANCTUM_STATEFUL_DOMAINS в файл .env, где хранятся все часто используемые переменные окружения Laravel. Кроме этого, так как запросы будут к адресам, которые начинаются с префикса api/, то и адрес /sanctum/csrf-token нужно переопределить на /api/sanctum/csrf-token. Сделать это можно также в файле config\sanctum.php, добавив параметр prefix, как это показано в листинге кода ниже.

<?php

return [

    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

...

    'prefix' => 'api/sanctum',

...

Откройте файл .env и добавьте в него переменную SANCTUM_STATEFUL_DOMAINS с доменом клиентской части разрабатываемого приложения:

APP_NAME  =Laravel
APP_ENV   =local
APP_KEY   =base64:N2fSCTcpaGSM0JMwVDYTev5wwOavz2hXKRcLb3vXGIQ=
APP_DEBUG =true
APP_URL   =http://localhost

SANCTUM_STATEFUL_DOMAINS=localhost:3000

Каждый раз, внося, какие-то изменения в конфигурационные файлы или маршруты нужно почистить кэш, чтобы изменения были применены:

php artisan cache:clear
php artisan config:clear
php artisan route:cache

3.3. Миграции

Убедитесь также, что в каталоге database\migrations есть файл миграции с текстом create_personal_access_tokens_table в названии:

2019_12_14_000001_create_personal_access_tokens_table.php

Эта миграция нужна для создания таблицы в базе данных, в которой будут храниться токены доступа всех пользователей, которые авторизовываются. Кроме этого, в каталоге миграций будут сразу после установки Laravel-проекта этой версии ещё вот такие файлы миграций:

  • create_users_table – создание таблицы пользователей.
  • create_password_resets_table – создание таблицы сброса паролей.
  • create_failed_jobs_table – создание таблицы неудачно завершённых заданий. 

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

php artisan migrate

В процессе успешного выполнения этой команды будет вот такой вывод:

Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Migrated:  2014_10_12_000000_create_users_table (382.62ms)
Migrating: 2014_10_12_100000_create_password_resets_table
Migrated:  2014_10_12_100000_create_password_resets_table (310.98ms)
Migrating: 2019_08_19_000000_create_failed_jobs_table
Migrated:  2019_08_19_000000_create_failed_jobs_table (260.71ms)
Migrating: 2019_12_14_000001_create_personal_access_tokens_table
Migrated:  2019_12_14_000001_create_personal_access_tokens_table (292.27ms)

А в базе данных Вы увидите, только что созданные таблицы:

Рис. 1 – Список таблиц базы данных в HeidiSQL.

Рис. 1 – Список таблиц базы данных в HeidiSQL.

3.4. HTTP-ядро

Теперь нужно перейти в файл app\Http\Kernel.php и добавить класс EnsureFrontendRequestsAreStateful (промежуточное ПО) в массив $middlewareGroups (раздел api), как показано в листинге кода ниже. EnsureFrontendRequestsAreStateful нужен для проверки запросов, соответствуют ли они текущему состоянию сессии. 

Кроме этого, здесь же мы можем установить общее ограничение (для всех api-маршрутов) по количеству запросов за определённый период времени. Это можно сделать, указав псевдоним (throttle) на класс ThrottleRequests, который объявлен в общей группе промежуточного программного обеспечения маршрутов (routeMiddleware). По умолчанию здесь установлено имя ограничителя api. Определение и настройку ограничителей можно делать в классе app\Providers\RouteServiceProvider. Устанавливать их нужно в методе configureRateLimiting(). Сейчас там для всех маршрутов установлено ограничение в 60 запросов в минуту. Далее в статье будет показано, как сделать именованный ограничитель и использовать его для отдельных маршрутов или групп маршрутов. 

...

    protected $middlewareGroups = [

	...

        'api' => [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
            'throttle:api',
            \Illuminate\Routing\Middleware\SubstituteBindings::class,
        ],
    ];

    protected $routeMiddleware = [
        ...

        'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,

        ...
    ];
}

По умолчанию для сессий в Laravel используется драйвер file, а время длительности сессии установлено на 120 минут. Для настройки сессий обратитесь к конфигурационному файлу config\session.php. Для удобства некоторые настройки вынесены в файл переменных окружения (.env).

SESSION_DRIVER   =file
SESSION_LIFETIME =120

На данном этапе можно всё оставить, как есть. Для наших экспериментов и тестов этого вполне достаточно.

3.5. Модель User

И завершающим этапом этой предварительной настройки для работы с пакетом Sanctum будет проверка подключенного трейта HasApiTokens. Для этого нужно открыть файл app\Models\User.php и добавить трейт в тело класса модели User, если его там нет.

<?php

namespace App\Models;

...

use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
    use HasApiTokens, HasFactory, Notifiable;

...

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


4. Tinker

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

Tinker – это дополнительный пакет, с помощью которого можно работать с кодом проекта прямо из командной строки, используя синтаксис PHP или Laravel

Для начала работы с Tinker введите в терминале такую команду:

php artisan tinker

После выполнения команды выше Вы увидите приглашение для ввода PHP-кода:

PS C:\laragon\www\mt5\api> php artisan tinker
Psy Shell v0.10.12 (PHP 7.4.6 — cli) by Justin Hileman
>>>

Для примера выполним простое вычисление:

>>> echo 3 + 5
8
>>>

А теперь создадим пользователя, указав его данные (имя, электронный адрес, пароль):

User::create(['name' => 'user', 'email' => 'user@mail.com', 'password' => Hash::make('123123123')])

В результате в терминале будет вот такой вывод:

[!] Aliasing 'User' to 'App\Models\User' for this Tinker session.
=> App\Models\User {#4412
     name: "user",
     email: "user@mail.com",
     #password: "$2y$10$vNyZmqrYkskpfsz9u6gP4uV3G9KegahQZTV9zlN6ZE4AXAf13Y1e2",
     updated_at: "2022-01-17 20:39:31",
     created_at: "2022-01-17 20:39:31",
     id: 1,
   }
>>>

Это означает, что всё прошло успешно и в таблице users появится новая строка с данными, только что добавленного пользователя:

Рис. 2 – Таблица Users в базе данных.

Рис. 2 – Таблица Users в базе данных.


5. Настройка окружения в Postman

Сначала настроим Postman для работы с API разрабатываемого приложения. Создадим рабочее пространство с именем MetaTrader 5 и затем коллекцию Laravel API. Для этого перейдите на вкладку Collections в панели слева и нажмите на кнопку с иконкой в виде плюса. В этот список можно добавить сколько угодно коллекций, чтобы создать удобную структуру. В коллекции Laravel API будут содержаться все запросы к серверной части проекта. 

Давайте сейчас в качестве теста добавим GET-запрос к главной (индексной) странице (http://localhost:8000/). Нажмите правой кнопкой на пункт в списке коллекций и выберите в контекстном меню пункт Add request (Добавить запрос). Введите параметры HTTP-запроса (имя, тип, адрес) и инициируйте его отправку, нажав кнопку Send. В итоге сервер вернёт содержимое страницы и на вкладке Preview Вы увидите такой же результат, как в браузере (см. скриншот ниже), а на вкладках Pretty и Raw Вы найдёте исходный код этой страницы.

Рис. 3 - Вкладка Collections с коллекциями и запросами.

Рис. 3 - Вкладка Collections с коллекциями и запросами.

Ещё нам нужно добавить переменные окружения для удобства. Это можно сделать на вкладке Environments, нажав кнопку с иконкой в виде плюса. Создайте новое окружение с именем Laravel API. Затем, создайте в таблице окружения переменную BASE_URL со значением http://localhost:8000 и переменную BASE_API_URL со значением http://localhost:8000/api. Они понадобятся для быстрого изменения точек доступа к приложению, если были внесены изменения в серверной части приложения. По умолчанию, в Laravel запросы к API нужно делать по адресам с префиксом api. Создадим также переменную TOKEN, которая будет использоваться для хранения персонального токена доступа предназначенного для авторизации пользователя.

Рис. 4 - Вкладка Environments с переменными окружения.

Рис. 4 - Вкладка Environments с переменными окружения.

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

{{BASE_API_URL}}/login

Результат будет таким же, как если бы Вы ввели адрес полностью:

http://localhost:8000/api/login

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

pm.environment.set("TOKEN", pm.response.json().token);

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


6. API-маршруты в Laravel

Все маршруты в Laravel определяются в каталоге routes. Изначально здесь находятся четыре файла:

  • api.php - для регистрации api-маршрутов приложения.
  • channels.php - для регистрации каналов трансляции событий.
  • console.php - для определения консольных команд.
  • web.php - для регистрации веб-маршрутов приложения.

В каждом из этих файлов есть дополнительные комментарии. Из них видно, что web- и api-маршруты загружаются провайдером RouteServiceProvider. Именно в нём в методе boot() определяется, к какой группе относятся маршруты из разных файлов, а также устанавливается промежуточное программное обеспечение (middleware) и определяется префикс api для всех api-маршрутов. Найти файл с классом RouteServiceProvider можно в каталоге app\Providers\RouteServiceProvider.php. Откройте этот файл, найдите строку, как показано ниже и раскомментируйте её:

protected $namespace = 'App\\Http\\Controllers';

Это пространство имен применяется к вашим маршрутам контроллера, а также устанавливается в качестве корневого пространства имен генератора URL.

Откройте файл routes\api.php. Там сейчас есть только один маршрут /user:

Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

Добавим в этот же файл свои маршруты. Для упрощения не будем сейчас создавать контроллеры для обработки запросов, чтобы быстро всё настроить и протестировать. К созданию контроллеров вернёмся немного позже.

Итак. Создадим три маршрута в файле routes\api.php, которые относятся к авторизации пользователя: (1) регистрация, (2) вход в систему, (3) выход из системы. На данном этапе вместо контроллеров обработка запросов будет осуществляться в функциях обратного вызова с максимально простым кодом. 

1. Маршрут регистрации пользователя. Делая запрос по этому адресу нужно передать такие параметры, как: (1) имя пользователя, (2) электронный адрес, (3) пароль. В модели User есть метод create() для создания и добавления пользователя в базу данных. При успешном выполнении этого действия, в ответе на HTTP-запрос отправим данные пользователя. 

Route::post('/register', function(Request $request) {
    $user = User::create([
        'name' => $request->name,
        'email' => $request->email,
        'password' => bcrypt($request->password)
    ]);
    return $user;
});

2. Маршрут для авторизации пользователя. Для этого маршрута нужно передать электронный адрес и пароль зарегистрированного пользователя. Если такой пользователь не найден, то срабатывает исключение c отправкой ответа на запрос с сообщением, что данные не прошли проверку. Если такой пользователь есть, то обновляем идентификатор сессии и сообщаем в ответе об успешной авторизации.

Сейчас сделаем небольшое отступление к ранее уже упомянутой теме. Если нужно создать свой именованный ограничитель запросов, который затем будет использоваться, как промежуточное программное обеспечение, для какого-то определённого маршрута или группы маршрутов, то перейдите в файл app\Providers\RouteServiceProvider.php к методу configureRateLimiting(). Сейчас здесь по умолчанию уже определён именованный ограничитель (api) для всех api-маршрутов. Но таких ограничителей можно создать сколько угодно и переопределить ограничения для тех или иных маршрутов. Добавим именованный ограничитель auth с ограничением пять запросов в минуту с одного ip-адреса, как показано в листинге ниже.

    protected function configureRateLimiting() {

        ...

        RateLimiter::for('auth', function (Request $request) {
            return Limit::perMinute(5)->by($request->ip());
        });
    }

Теперь, чтобы применить именованный ограничитель (auth) для маршрута авторизации просто добавьте к нему промежуточное программное обеспечение (middleware) так, как показано ниже:

Route::middleware('throttle:auth')->post('/login', function(Request $request) {
    $credentials = $request->only('email', 'password');
    if (!auth()->attempt($credentials)) {
        throw ValidationException::withMessages([
            'login' => 'Invalid credentials'
        ]);
    }
    $request->session()->regenerate();
    return response()->json([
        'message' => 'You are logged in!'
    ], 200);
});

3. Маршрут для выхода из приложения. Сделав запрос по этому маршруту пользователь выходит из системы, данные сессии удаляются и регенерируется значение CSRF-токена.

Route::get('/logout', function(Request $request) {
    auth()->logout();
    $request->session()->invalidate();
    $request->session()->regenerateToken();
    return response()->json([
        'message' => 'You are logged out!'
    ], 200);
});

Для верификации CSRF-токена используется промежуточное программное обеспечение app\Http\Middleware\VerifyCsrfToken.php, где можно исключить маршруты от проверки на соответствие CSRF-токена. Для этого нужно просто добавить маршрут в массив $except, как показано ниже. Здесь мы исключаем маршрут для регистрации пользователя

class VerifyCsrfToken extends Middleware
{
    protected $except = [
        'api/register'
    ];
}

Просмотреть весь список зарегистрированных маршрутов в Laravel можно с помощью такой команды:

php artisan route:list

Результат выполнения:

+--------+----------+-------------------------+-----------------------------+------------------------------------------------------------+------------------------------------------+
| Domain | Method   | URI                     | Name                        | Action                                                     | Middleware                               |
+--------+----------+-------------------------+-----------------------------+------------------------------------------------------------+------------------------------------------+
|        | GET|HEAD | /                       | generated::ho5sCoUTxzzXdBi7 | Closure                                                    | web                                      |
|        | POST     | api/login               | generated::RHpEv2K9xtzsqlhd | Closure                                                    | api                                      |
|        | GET|HEAD | api/logout              | generated::CTXVk1V2MDt9zYCt | Closure                                                    | api                                      |
|        | POST     | api/register            | generated::QHDPtTGp41RBsDBM | Closure                                                    | api                                      |
|        | GET|HEAD | api/sanctum/csrf-cookie | generated::6t2mQERpO9Fazfbe | Laravel\Sanctum\Http\Controllers\CsrfCookieController@show | web                                      |
|        | GET|HEAD | api/user                | generated::2B2PmhDJOnbHJHEA | Closure                                                    | api                                      |
|        |          |                         |                             |                                                            | App\Http\Middleware\Authenticate:sanctum |
+--------+----------+-------------------------+-----------------------------+------------------------------------------------------------+------------------------------------------+

Давайте теперь протестируем эти маршруты в Postman


7. Тестируем маршруты авторизации

Перейдите в Postman и создайте в ранее добавленной коллекции Laravel API папку Auth, а в ней папку Secured. В эту папку будем добавлять маршруты, к которым можно получить доступ только при наличии XSRF-токена. 

Информация из Википедии (подробнее):

CSRF (англ. cross-site request forgery — «межсайтовая подделка запроса», также известна как XSRF) — вид атак на посетителей веб-сайтов, использующий недостатки протокола HTTP.

Чтобы получить XSRF-токен, нужно сделать запрос по маршруту /sanctum/csrf-cookie. Во время этого запроса система установит XSRF-куки, в котором будет содержаться текущий CSRF-токен. При последующих запросах этот токен нужно всегда передавать в заголовке X-XSRF-TOKEN. Будет использоваться жёсткий вариант этого механизма, когда уникальный одноразовый ключ генерируется при каждом запросе. 

Давайте создадим запрос Sanctum CSRF-cookie в коллекции Laravel API для получения XSRF-токена, чтобы убедиться, что это работает. После этого, не спешите отправлять запрос нажатием кнопки Send, а обратите сначала внимание на кнопку Cookie справа от вкладок запроса.

Рис. 5 – Запрос для получения XSRF-токена.

Рис. 5 – Запрос для получения XSRF-токена.

Нажатие на кнопку Cookie вызывает окно Manage Cookie:

Рис. 6 – Окно Manage Cookie.

Рис. 6 – Окно Manage Cookie.

На текущий момент здесь, как видно, ничего нет. Но если начать делать запросы, то здесь будут сохраняться куки от различных веб-сайтов. Закройте это окно и нажмите на кнопку Send, чтобы сделать запрос по маршруту /sanctum/csrf-cookie

После успешного выполнения запроса Вы сможете увидеть изменения в нескольких разделах Postman

  • Окно Manage Cookie
  • Заголовки запроса автоматически дополняются заголовком Cookie
  • Вкладки Cookie и Headers с результатами ответа сервера
  • Консоль

Рис. 7 – Исследование результата запроса на содержание куки.

Рис. 7 – Исследование результата запроса на содержание куки.

Как видно на скриншоте выше, в результате запроса были получены куки с данными сессии (laravel_session) и токен доступа (XSRF-TOKEN). 

В процессе экспериментов Вам может понадобится удалить все куки, чтобы посмотреть, какие ответы даёт сервер в различных сценариях. Для удаления нужно открыть окно Manage Cookie и нажать на кнопку очистки хранилища для того или иного домена.

Рис. 8 – Удаление куки.

Рис. 8 – Удаление куки.

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

  • X-XSRF-TOKEN – ключ для защиты от межсайтовой подделки запроса.
  • Accept – указывает, какие типы контента может понять клиент.
  • Referer – адрес исходной страницы, с которой был осуществлён запрос.

Вместо того, чтобы добавлять эти заголовки вручную для каждого запроса, можно написать скрипт, который будет запускаться для всех запросов в группе перед их отправкой. А когда приходит ответ от сервера нужен скрипт, который будет получать значение куки XSRF-TOKEN и сохранять его в переменную окружения TOKEN. Чтобы добавить такой общий скрипт кликните левой кнопкой мыши на папке. В нашем случае это папка Secured. В открывшейся рабочей области папки Вы увидите три вкладки: Authorization, Pre-request Script, Tests. Нас сейчас интересуют две из них: 

  • Pre-request Script – скрипт из этой вкладки будет выполняться перед каждым запросом в этой папке.
  • Tests - эти тесты будут выполняться после каждого запроса в этой папке.

В листинге ниже показан скрипт, который будет выполняться перед каждым запросом. Здесь просто добавляем нужные для запроса заголовки в виде пар ключ/значение. Те заголовки, которые уже есть в запросе по умолчанию, например Accept, будут переопределены значением, указанным в этом скрипте. Обратите также внимание, что значение для заголовка X-XSRF-TOKEN получаем из переменной окружения TOKEN.

pm.request.headers.add({
  key: 'X-XSRF-TOKEN',
  value: pm.environment.values.get('TOKEN')
});
pm.request.headers.add({
  key: 'Accept',
  value: 'application/json'
});
pm.request.headers.add({
  key: 'Referer',
  value: 'localhost:3000'
});

Скрипт для сохранения токена после получения ответа сервера для каждого запроса работает следующим образом. Получаем значение куки XSRF-TOKEN, который пришёл в ответе и сохраняем в переменной окружения TOKEN. Этот скрипт нужно добавить для папки Secured и отдельно для запроса /sanctum/csrf-cookie (также на вкладке Tests), так как он находится вне этой папки.

let token = pm.cookies.get('XSRF-TOKEN');
pm.environment.set("TOKEN", token);

Всё должно быть так, как показано на скриншоте ниже:

Рис. 9 – Скрипты для работы с заголовками.

Рис. 9 – Скрипты для работы с заголовками.

Теперь можно добавить несколько маршрутов в папку Secured:

  • LoginPOST-запрос для авторизации пользователя. В этом запросе нужно передать данные формы, в которых должны содержаться (1) электронный адрес и (2) пароль пользователя, который он указывал при регистрации. Добавить эти данные можно на вкладке запроса Body (см. скриншот ниже):

Рис. 10 – Форма данных запроса на вкладке Body.

Рис. 10 – Форма данных запроса на вкладке Body.

  • UserGET-запрос на получение данных авторизованного пользователя. 
  • LogoutGET-запрос для выхода пользователя из системы (закрытие сессии).

Запрос Register нужно поместить в папке Auth (вне папки Secured):

  • RegisterPOST-запрос для регистрации пользователя. В этом запросе нужно передать данные формы, в которых должны содержаться (1) имя, (2) электронный адрес и (3) пароль пользователя.

Если сейчас попытаться авторизоваться в системе без наличия XSRF-токена, то сервер отдаст ответ с сообщением об ошибке, что токен не соответствует (код ошибки 419):

Рис. 11 – Несоответствие CSRF-токена (код ошибки 419).

Рис. 11 – Несоответствие CSRF-токена (код ошибки 419).

Но, если сначала сделать запрос по маршруту /sanctum/csrf-cookie, как это было показано ранее, и после этого попробовать авторизоваться, то всё пройдёт успешно. Результатом авторизации будет код 200 и сообщение о том, что авторизация прошла успешно:

{
    "message": "You are logged in!"
}

А результатом регистрации нового пользователя будет код 200 и JSON-объект с данными созданного пользователя. 

{
    "name": "test",
    "email": "test@mail.com",
    "updated_at": "2022-01-25T09:15:17.000000Z",
    "created_at": "2022-01-25T09:15:17.000000Z",
    "id": 8
}

Отправка запроса по маршруту /logout должна дать результат с кодом 200 и таким сообщением:

{
    "message": "You are logged out!"
}

Если же сделать запрос на получение данных пользователя до авторизации, то ответ будет с кодом 401 и сообщением о том, что пользователь не авторизован:

{
    "message": "Unauthenticated."
}

Но если сначала войти в систему, то результатом запроса будет код 200 и JSON-объект с данными пользователя:

{
    "id": 1,
    "name": "user",
    "email": "user@mail.com",
    "email_verified_at": null,
    "created_at": "2022-01-17T20:39:31.000000Z",
    "updated_at": "2022-01-17T20:39:31.000000Z"
}

Ранее мы создали именованный ограничитель auth и применили его к маршруту авторизации /login. Теперь давайте протестируем, как работает ограничение по количеству запросов. Если сейчас сделать запрос по этому маршруту, то в списке заголовков ответа сервера Вы увидите заголовки, на которые следует сейчас обратить внимание:

  • X-RateLimit-Limit - максимальное количество запросов, которое можно выполнить за определённый период времени.
  • X-RateLimit-Remaining – оставшееся количество запросов, которое ещё можно выполнить в рамках установленного ограничения.

...

X-RateLimit-Limit: 5
X-RateLimit-Remaining: 4

...

Когда ограничение достигнуто, возвращается код ответа 429 (Too Many Requests) и при этом появляется ещё один заголовок:

  • Retry-After – время (секунды), через которое можно попробовать снова выполнить свой запрос.

...

X-RateLimit-Limit: 5
X-RateLimit-Remaining: 0
Retry-After: 44

...

Что же касается других маршрутов, то можно ещё привести пример с маршрутом регистрации /register. Попробуйте выполнить запросы в программе Postman и Вы обнаружите, что рассмотренные выше заголовки показывают уже совсем другие значения:

Рис. 12 – Группа заголовков X-RateLimit в ответе сервера.

Рис. 12 – Группа заголовков X-RateLimit в ответе сервера.

Это пока всё, что нужно знать для тестирования маршрутов в Postman. Далее займёмся реализацией клиентской части приложения.


8. Настройка веб-приложения в Nuxt

В предыдущей статье мы уже создали проект для разработки с фреймворком Nuxt. Теперь нужно установить необходимые для разработки пакеты и настроить окружение. Кроме этого, для удобной отладки разрабатываемого веб-приложения нужно установить расширение браузера (Chrome или Firefox) Vue.js devtools

8.1. Расширение Vue.js devtools

Запустите проект в режиме разработки командой npm run dev. Когда приложение запущено в режиме разработки, то любые изменения будут автоматически перезагружать страницу в браузере. Если расширение Vue.js devtools уже установлено, то после открытия страницы Vue-приложения в браузере расширение автоматически определит, что приложение открыто в режиме разработки и в панели разработчика браузера (F12) появится вкладка Vue. Здесь удобно отслеживать любые изменения приложения в компонентах, хранилище данных, истории переходов и т.д. 

Рис. 13 – Расширение браузера Vue.js devtools для отладки Vue-приложений.

Рис. 13 – Расширение браузера Vue.js devtools для отладки Vue-приложений.

8.2. Переменные окружения

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

На данном этапе добавьте такие переменные в файл .env

  • SCHEME - протокол передачи данных.
  • BASE_URL - базовый адрес клиентского приложения.
  • API_DOMAIN - базовый адрес серверной части приложения.
  • API_URL - адрес серверного API.

SCHEME     = http://
BASE_URL   = http://localhost:3000
API_DOMAIN = http://localhost:8000
API_URL    = http://localhost:8000/api

8.3. Установка дополнительных пакетов

Ниже показан список тех пакетов, которые понадобятся на данном этапе:

  • @nuxtjs/auth-next – модуль для авторизации пользователей.
  • @nuxtjs/axios – этот модуль предназначен для отправки HTTP-запросов. Поддерживает Promise (отложенные и асинхронные вычисления) и автоматически преобразует JSON-данные.
  • @nuxtjs/dotenv – этот модуль загружает файл .env (переменные окружения) в опции контекста. Обращение к переменным окружения можно сделать так: process.env.<variable_name> (<variable_name> заменить на имя переменной).
  • @nuxtjs/proxy – этот модуль будет использоваться для изменения (сокращения) URL-адресов в соответствии с текущим именем хоста при обращении к API серверной части приложения.
  • view-design – набор компонентов пользовательского интерфейса.

Этого пока достаточно для наших тестов. Далее рассмотрим установку и настройку этих модулей. 

В Node.js пакеты устанавливаются с помощью пакетного менеджера npm. Если Вы следовали инструкциям в предыдущей статье, то у Вас он уже установлен вместе с Node.js. Для установки пакета достаточно ввести вот такую команду (<package_name> заменить на имя пакета):

npm install <package_name> 

Например, для установки пакета @nuxtjs/dotenv введите эту команду, как показано в листинге ниже. Обратите внимание, что можно указать сокращённый вариант (i вместо install).

npm i @nuxtjs/dotenv

Таким же образом установите все остальные пакеты, которые были перечислены в списке выше. Во время установки Вы можете увидеть вот такие предупреждения:

...

npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@2.3.2 (node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@2.3.2: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@1.2.13 (node_modules\watchpack-chokidar2\node_modules\fsevents):
npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for fsevents@1.2.13: wanted {"os":"darwin","arch":"any"} (current: {"os":"win32","arch":"x64"})

...

Можно не обращать внимание на это. Здесь говорится лишь о том, что зависимость fsevent@2.3.2 предназначена для разработки в среде macOS.

После установки пакета он автоматически добавляется в список зависимостей проекта в файле package.json, который находится в корневой директории проекта.

{

...

  "dependencies": {
    "@nuxtjs/auth-next": "^5.0.0-1643103966.eefc505",
    "@nuxtjs/axios": "^5.13.6",
    "@nuxtjs/dotenv": "^1.4.1",
    "@nuxtjs/proxy": "^2.1.0",
    "core-js": "^3.9.1",
    "nuxt": "^2.15.3",
    "view-design": "^4.7.0"
  },
  
...

}

Кроме пакетов, которые будут использоваться в производственной среде, нам понадобятся также вспомогательные пакеты для разработки. К таким относятся node-sass и sass-loader, которые нужны загрузки и компиляции файлов Sass/SCSS в CSS.

Так как эти пакеты предназначены только для разработки, то команду нужно вводить с дополнительным параметром --save-dev. Также можно указать, какие-то конкретные версии пакетов, которые актуальны для Вашего окружения. 

npm i node-sass@6.0.1 --save-dev

Для продолжения работы в файле package.json должно быть вот так:

{

...

  "devDependencies": {
    "node-sass": "^6.0.1",
    "sass-loader": "^10.2.0"
  }
}

8.4. Конфигурационный файл

Для активации установленных модулей нужно добавить их в главном конфигурационном файле nuxt.config.js, который можно найти в корневом каталоге. Откройте этот файл и добавьте в массив modules установленные модули, как показано ниже: 

export default {

...

  modules: [
    '@nuxtjs/dotenv',
    '@nuxtjs/axios',
    '@nuxtjs/proxy',
    '@nuxtjs/auth-next',
  ],

...

}

Далее в этом же конфигурационном файле нужно добавить настройки, на основе которых эти модули будут работать.

Для модуля @nuxtjs/axios нужно добавить параметр credentials для установки куки, которые были переданы в ответе сервера. 

export default {

...

  axios: {
    credentials: true
  },

...

}

Для модуля @nuxtjs/proxy нужно добавить следующий блок. Здесь указано, чтобы при каждом запросе адрес начинался с /api. В запросах при этом не нужно писать весь адрес. Например, вместо http://example.com/api/login пишите краткую форму /login

export default {

...

  proxy: {
    "/api": {
      target: process.env.API_DOMAIN,
      pathRewrite: { "^/api": "/" }
    }
  },

...

}

Модуль @nuxtjs/auth-next уже включает поддержку системы авторизации Laravel Sanctum. Для настройки этой системы в Nuxt-проекте нужно добавить блок со следующими параметрами. 

В разделе redirect указываются адреса для перенаправления пользователя в зависимости от его текущего статуса. 

В разделе strategies может использоваться несколько различных систем для авторизации пользователя. В данном случае устанавливаем пока только блок laravelSanctum. Здесь указываем (1) провайдера, (2) адрес к API, (3) конечные точки для системы авторизации. 

export default {

...

  auth: {
    redirect: {
      login: '/auth/login',
      logout: '/',
      home: '/',
    },
    strategies: {
      laravelSanctum: {
        provider: "laravel/sanctum",
        url: process.env.API_URL,
        endpoints: {
          login: { url: '/login' },
          user: { url: '/user' },
          logout: { url: '/logout', method: 'get' },
        },
      },
    }
  },

...

}

8.5. Централизованное хранилище данных Vuex Store

Для того, чтобы активировать хранилище данных Vuex Store, достаточно создать пустой файл index.js в каталоге store. Содержимое относящееся к системе авторизации будет формироваться автоматически. 

Откройте страницу в браузере и затем откройте панель разработчика (F12). Перейдите на вкладку Vue и откройте раздел Vuex. Выделите последнее действие в списке слева, чтобы увидеть текущее состояние Вашего приложения. На текущий момент нас интересует блок auth. Здесь можно увидеть, что auth это объект, свойства которого показывают нам, (1) авторизован ли пользователь (loggedIn), (2) какая стратегия авторизации используется (strategy), (3) получен ли объект с данными пользователя. В данном случае видно, что пользователь неавторизован, так как loggedIn содержит значение false. А следовательно, данные пользователя не получены (user: null).

Рис. 14 – Текущее состояние Vue-приложения.

Рис. 14 – Текущее состояние Vue-приложения.

Кроме этого, объект auth предоставляет методы для авторизации и выхода из системы. Примеры их использования мы рассмотрим далее в статье. 


9. Графический интерфейс веб-приложения

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

9.1. Библиотека view-design

Те модули, у которых есть более широкие возможности для настройки, подключаются к проекту в виде плагинов. Для таких случаев есть отдельный каталог plugins. Создайте в этом каталоге папку ui, а в ней файл iview.js. В этом файле подключаем к проекту объект view-design с указанием локализации и размера элементов по умолчанию, как показано в листинге ниже. На данном этапе этого достаточно, чтобы начать работу.

import Vue from 'vue';
import ViewUI from 'view-design';

export default () => {
    Vue.use(ViewUI, {
        locale: 'en',
        size: default // small | default | large
    });
}

Файлы плагинов подключаются к проекту в конфигурационном файле nuxt.config.js в массиве plugins, как показано ниже. У объекта плагина есть два свойства: src и ssr. Первое свойство указывает путь к файлу. Второе - доступен ли файл при рендеринге на стороне сервера. 

export default {

...

  plugins: [
    { src: '~/plugins/ui/iview.js', ssr: true },
  ],

...

}

Чтобы не настраивать CSS-стили для каждого компонента самим, установим те, которые предоставляет библиотека view-design. Для этого создайте в каталоге assets папку scss и в ней файл app.scss. К этому файлу можно подключать стили различных библиотек, которые будете устанавливать для своего проекта или пользовательские стили, которые создаёте сами. В этом же случае добавьте туда пока только одну строку:

@import 'view-design/dist/styles/iview.css';

Файл app.scss нужно подключить к конфигурационному файлу nuxt.config.js, чтобы он стал доступен для использования: 

export default {

...

  css: [
    '~/assets/scss/app.scss'
  ],

...

}

9.2. Layouts

В каталоге layouts можно создавать vue-файлы, которые будут использоваться, как многократно используемые макеты (обёртки) для страниц приложения. По умолчанию там только один файл - default.vue, и этого будет пока достаточно. Но можно создать сколько угодно макетов, если есть такая необходимость. 

В макете default.vue создадим максимально краткий шаблон, в котором есть шапка сайта со ссылками для перехода на другие страницы: (1) главная страница, (2) страница с формой для авторизации пользователя, (3) страница с формой для регистрации пользователя, (4) страница администратора, (5) кнопка для выхода из системы. Шаблон формируется с учётом текущего статуса пользователя. То есть, если он неавторизован, то показываются кнопки для входа (Login) и регистрации (Registry). Если же уже авторизовался, то показываются кнопки для перехода в администраторскую часть приложения (Dashboard) и для выхода из системы (Logout). Обращаться к свойствам и методам авторизации нужно через глобальный объект this.$auth

Содержимое страниц будет подставляться автоматически вместо компонента Nuxt. В этом и заключается удобство использования макетов. 

<template>
  <div class="layout">
    <Layout>
      <Header :style="{width: '100%', zIndex: '2'}">
        <Row type="flex" justify="space-between" :wrap="false">
          <Col span="5" :style="{minWidth: '140px'}">
            <div class="layout-logo">
              <nuxt-link to="/">LOGO</nuxt-link>
            </div>
          </Col>
          <Col flex="auto">
            <div class="layout-nav">
              <template v-if="!$auth.loggedIn">
                <nuxt-link to="/auth/login">Login</nuxt-link>
                <nuxt-link to="/auth/register">Register</nuxt-link>
              </template>
              <template v-else>
                <nuxt-link to="/admin/dashboard">Dashboard</nuxt-link>
                <a href="#" @click.prevent="logout()">Logout</a>
              </template>
            </div>
          </Col>
        </Row>
      </Header>
      <Content :style="{margin: '20px auto', padding: '20px'}">
        <Nuxt />
      </Content>
    </Layout>
  </div>
</template>

...

В блоке script файла default.vue обрабатывается только нажатие на кнопке Logout, которое осуществляет выход из системы с помощью метода logout() объекта $auth.

<script>
export default {
  methods: {
    async logout() {
      try {
        await this.$auth.logout();
        this.$Message.success('Success!');
      } catch (error) {
        this.$Message.error('Fail!');
        console.log(error);
      }
    }
  }
}
</script>

На данный момент в браузере это выглядит так, как показано на скриншоте ниже. Содержание этой (главной) страницы Вы можете посмотреть в файле pages\index.vue.

Рис. 15 – Главная страница приложения.

Рис. 15 – Главная страница приложения.

9.3. Middleware

Как было продемонстрировано выше, те или иные кнопки показываются по условию - авторизован ли пользователь. Но этого недостаточно, чтобы заблокировать доступ к тем или иным страницам. Например, если пользователь авторизован, то попытка перейти на страницу авторизации (http://localhost:3000/auth/login) через ввод адреса в адресной строке браузера, должна перенаправлять пользователя на главную страницу. А если неавторизован, то попытка перейти в скрытую часть приложения (http://localhost:3000/admin/dashboard), будет перенаправлять пользователя на страницу авторизации. 

Для того, чтобы реализовать такую схему будем использовать промежуточное программное обеспечение (middleware), предназначение которого заключается в том, чтобы выполняться до того, как был осуществлён переход по тому или иному маршруту. И если в процессе проверки выясняется, что страница недоступна для текущего статуса пользователя, то осуществляется перенаправление на другую страницу.

Что касается страниц, которые доступны только авторизованным пользователям, то для этого случая установленный пакет @nuxtjs/auth-next уже предоставляет свой middleware. И для подключения к странице достаточно указать это в скриптовой части vue-файла, как показано в листинге кода ниже. 

...

<script>
export default {
  middleware: ['auth'],
...
}
</script>

...

Для тех страниц, которые могут быть доступны только для неавторизованных пользователей создадим своё промежуточное ПО. Для этого в каталоге middleware создайте папку auth и в ней файл guest.js. Добавьте в этот файл код, как показано в листинге ниже. Здесь достаточно краткого пояснения о том, что глобальный контекст приложения передаётся в функцию, как параметр app. Это нужно для доступа к глобальному объекту $auth. Следуя дальнейшей логике, то по условию, когда пользователь авторизован, нужно перенаправить его на главную страницу.

export default ({app, redirect}) => {
  if (app.$auth.loggedIn) {
    return redirect('/');
  }
}

Так как этот middleware расположен в каталоге middleware\auth\guest.js, то его нужно подключать, указывая путь к нему:

...

<script>
export default {
  middleware: ['auth/guest'],
...
}
</script>

...

9.4. Pages

В каталоге pages можно создавать vue-файлы, которые автоматически определяются Nuxt, как страницы сайта с маршрутами в соответствии с расположением в этом каталоге. Нам понадобятся для тестов файлы, как показано в структуре ниже:

+---pages
|   |   index.vue
|   |   
|   +---admin
|   |       dashboard.vue
|   |       
|   \---auth
|           login.vue
|           register.vue
|           

Например, содержимое файла pages\index.vue будет доступно по адресу http://localhost:3000, а содержимое файла pages\auth\register.vue можно увидеть по адресу http://localhost:3000/auth/register.

Для примера, кратко рассмотрим файл страницы авторизации пользователя (pages\auth\login.vue). Файл страницы регистрации устроен аналогично. В коде шаблона из компонентов библиотеки view-design собрана форма авторизации. Правила валидации данных указываются в параметре rules компонента Form. В этот параметр передаётся объект ruleInline, где для каждого поля формы указываются правила, которые будут проверятся на стороне клиента.

Для больших подробностей о том, какие ещё есть параметры у компонентов view-design Вам следует обратиться к документации этой библиотеки.

<template>
  <div class="container">
    <h1>Login</h1>
    <br>
    <Form ref="formInline" :model="formInline" :rules="ruleInline" :label-width="90">
      <FormItem label="Email:" prop="email">
        <Input type="text" v-model="formInline.email" placeholder="Enter your email..."></Input>
      </FormItem>
      <FormItem label="Password:" prop="password">
        <Input type="password" password v-model="formInline.password" placeholder="Enter your password..."></Input>
      </FormItem>
      <FormItem>
        <Button type="primary" @click="handleSubmit('formInline')">Sign in</Button>
      </FormItem>
    </Form>
  </div>
</template>

Объект ruleInline с правилами валидации показан в листинге ниже. Здесь для поля email добавлено одно правило, у которого в параметрах указано, что поле обязательно для заполнения. Для поля password одно из двух правил такое же, как у поля email. А второе правило говорит о том, что это должно быть строковое значение и строка должна быть не менее 9 символов. Сообщения с подсказками показываются при смене фокуса с поля ввода.

...

<script>
export default {
  middleware: ['auth/guest'],
  data() {
    return {
      formInline: {
        email: '',
        password: ''
      },
      ruleInline: {
        email: [
          { required: true, message: 'Please fill in the email', trigger: 'blur' }
        ],
        password: [
          { required: true, message: 'Please fill in the password.', trigger: 'blur' },
          { type: 'string', min: 9, message: 'At least 9 characters', trigger: 'blur' }
        ]
      }
    }
  },
...
}
</script>

...

Проверка правил валидации осуществляется ещё раз до отправки формы. Затем для авторизации пользователя вызывается метод loginWith() объекта this.$auth. В качестве аргументов передаётся название стратегии авторизации и объект с данными пользователя. Для примера результаты валидации и запросов будут сопровождаться всплывающими сообщениями и выводом в консоль браузера в панели разработчика (F12).

...

<script>
export default {

...

  methods: {
    handleSubmit(name) {
      this.$refs[name].validate((valid) => {
        if(valid) {
          this.$auth.loginWith('laravelSanctum', {
            data: this.formInline,
          })
          .then((response) => {
            console.log(response);
            this.$Message.success('Success!');
          })
          .catch((error) => {
            console.log(error);
            this.$Message.error('Fail!');
          });
        } else {
          this.$Message.error('Fail!');
        }
      });
    }
  }
}
</script>

...

С кодом остальных страниц Вы можете ознакомиться самостоятельно загрузив файлы проекта в конце статьи.

После запуска проекта Вы увидите в браузере вот такой результат:

Рис. 16 – Демонстрация веб-приложения в браузере.

Рис. 16 – Демонстрация веб-приложения в браузере.


10. Заключение

В статье подробно показаны все этапы для установки и настройки системы авторизации Laravel Sanctum, как в серверной части (Laravel), так и в клиентской части (Nuxt). Материал в данной статье не покрывает абсолютно всех нюансов в реализации системы авторизации пользователей, так как целью данной статьи было показать только основной принцип, который будет в итоге перенесён в MQL5-приложение.

Так как статья получилась очень большой, то продолжение Вы сможете прочитать в следующей главе. В ней будет реализовано MQL5-приложение с возможностью авторизации в созданном веб-приложении в этой статье. Система авторизации будет создана на чистом MQL5.

К статье приложены архивы с файлами проектов для Laravel и Nuxt, чтобы Вы смогли их загрузить к себе и протестировать. Если Вы следовали инструкциям в предыдущей статье (Веб-проекты (Часть I): Создание веб-приложения в схеме Laravel/Nuxt/MetaTrader 5), где описывалось, как настроить своё окружение для веб-разработки в операционных системах Windows 10 и Ubuntu, то результат должен получиться такой же. В любом случае, не стесняйтесь задавать свои вопросы в комментариях к статье на форуме, если что-то не получается. Попробуем разобраться вместе. 


Прикрепленные файлы |
mt5-web-project.zip (232.78 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (12)
Andrei Novichkov
Andrei Novichkov | 15 февр. 2022 в 11:49
Мне тоже понравилось. И продолжение прочитаю с интересом.
Anatoli Kazharski
Anatoli Kazharski | 15 февр. 2022 в 16:40
Valeriy Yastremskiy #:

...

Да, конечно правильней сперва апачи с пхп изучить.

...

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

Valeriy Yastremskiy
Valeriy Yastremskiy | 16 февр. 2022 в 07:39
Anatoli Kazharski #:

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

Для полного понимания темы без разницы какой сервер понимать))) Наш Nginx  даже круче чем Апачи вроде местами.

Vadimvdv
Vadimvdv | 20 февр. 2022 в 12:17

Анатолий, спасибо за труд! Лично для меня огромную ценность будет представлять MQL5 websocket client, чтобы интегрировать с Django Python вебсокет сервером.Когда думаете выйдет статья с Вашем решением?

Будет ли реализован функционал по получению NUXT клиентом котировок, списка сделок, отправка ордеров с NUXT клиента в MT5 через сервер на PHP?

Anatoli Kazharski
Anatoli Kazharski | 20 февр. 2022 в 13:53
Vadimvdv #:

...

Сначала выйдет статья с реализацией системы авторизации пользователей в схеме Laravel/MetaTrader 5.

Пример с использованием веб-сокетов в MQL-приложении в связке Laravel/Nuxt/MetaTrader 5 будет следующим (уже готова).

Сейчас занимаюсь реализацией всего остального.

Использование класса CCanvas в MQL приложениях Использование класса CCanvas в MQL приложениях
Статья об использовании класса CCanvas в MQL приложениях с подробным разбором и примерами, что даёт пользователю понимание основ работы с данным инструментом
Графика в библиотеке DoEasy (Часть 96): Работа с событиями мышки и графика в объектах-формах Графика в библиотеке DoEasy (Часть 96): Работа с событиями мышки и графика в объектах-формах
В статье начнём разработку функционала для работы с событиями мышки в объектах-формах и добавим новые свойства и их отслеживание в объект-символ. Помимо этого сегодня доработаем класс объекта-символа, так как с момента его написания у символов графика появились новые свойства, которые желательно учитывать и отслеживать их изменение.
Шаблон проектирования MVC и возможность его использования (Часть 2): Схема взаимодействия между тремя компонентами Шаблон проектирования MVC и возможность его использования (Часть 2): Схема взаимодействия между тремя компонентами
Данная статья продолжает и завершает тему, поднятую в прошлой статье — шаблон MVC в программах на MQL. В этой статье мы рассмотрим возможную схему взаимодействия между этими тремя компонентами.
Матрицы и векторы в MQL5 Матрицы и векторы в MQL5
Специальные типы данных matrix и vector позволяют писать код, приближенный к математической записи. Это избавляет от необходимости создавать вложенные циклы и помнить о правильной индексации массивов, которые участвуют в вычислении. Таким образом повышается надежность и скорость разработки сложных программ.