Bootprainpping Laravel + Admiral: Auth без шаблона

Bootprainpping Laravel + Admiral: Auth без шаблона

29 июля 2025 г.

Вы знаете тренировку. Сверните Laravel, приклеивайте на переднем крае, снимайте в тупик, вместе некоторую аутентификацию и притворяйтесь, что повторение не сводит вас с ума. Большинство административных панелей одинаковы - аут, несколько маршрутов, форма или два, может быть, таблица. И все же, как -то, я всегда ловлю себя впустую, трачу полдня, восстанавливая те же чертовы леса, которые я построил на прошлой неделе.

Это то, что заставило меня построить адмирал-панель административной панели с открытым исходным кодом, который хорошо играет с Ларавелом и пропускает уток. Вы можете проверить этоздесь, но то, что я действительно хочу сделать, это пройти через реальную установку: Laravel + Admiral с аутентификацией с использованием святилища. Минимальная церемония, просто рабочая установка, которая уходит с вашего пути, чтобы вы могли отправить функции.

Шаг 1: Установка Laravel

Я начал с создания новой папки проекта:

mkdir admiral-laravel-init && cd admiral-laravel-init

Далее я установил Laravel во всем мире:

composer global require laravel/installer

Затем я создал новое приложение Laravel в справочнике.

Я пошел с SQLite для простоты, но не стесняйтесь использовать MySQL, Postgres или что -то еще.

Чтобы проверить, что работает, я бежал:

cd backend && composer run dev

Как только Dev Server начнется, он печатает APP_URL. Для меня это было:

APP_URL: http://localhost:8000

Открытие этого в браузере подтвердило, что Laravel был запущен и работал.

Шаг 2: Установка адмирала

Чтобы начать панель администратора, я бежал:

npx create-admiral-app@latest

Во время установки я выбрал:
«Установите шаблон без настройки бэкэнда»,
И для названия проекта я вступилadminПолем

Это дало мне новый каталог:admiral-laravel-init/adminПолем Я вскочил в него и установил зависимости:

cd admin && npm i

Затем я обновил файл .env, чтобы указать на бэкэнд Laravel:

VITE_API_URL=http://localhost:8000/admin

Теперь я построил и запустил адмирал -фронт:

npm run build && npm run dev

Как только сервер Dev встал, я увидел это в терминале:

Local: http://localhost:3000/

Открытие этого URL показал/loginстраница. Идеальный.

Шаг 3: Настройка аутентификации

Как с Admiral, так и с Laravel Live пришло время подключить аутентификацию с использованием Laravel Sanctum и AdmiralAuthProviderинтерфейс.

Установить святилище

Сначала я установил Laravel Sanctum:

php artisan install:api

Затем я открыл config/auth.php и зарегистрировал новый администратор:

'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'sanctum',
'provider' => 'users',
],
],

Далее я добавилHasApiTokensЧертаUserмодель:

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

Authcontroller.php

Теперь пришло время создать фактический AuthController:

<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests\LoginRequest;
use App\Services\Admin\Auth\AuthService;
use Illuminate\Validation\ValidationException;
use App\Http\Resources\AuthUserResource;
use App\Services\Admin\Auth\LimitLoginAttempts;
class AuthController
{
use LimitLoginAttempts;
public function __construct(
private readonly AuthService $auth,
) {
}
public function getIdentity(Request $request): array
{
$user = $request->user();
return [
'user' => AuthUserResource::make($user),
];
}
public function checkAuth(Request $request): \Illuminate\Http\JsonResponse
{
return response()->json('ok', 200);
}
public function logout(Request $request): void
{
$request->user()->currentAccessToken()->delete();
}
public function login(LoginRequest $request): array
{
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
$this->sendLockoutResponse($request);
}
try {
$user = $this->auth->login($request->email(), $request->password());
} catch (ValidationException $e) {
$this->incrementLoginAttempts($request);
throw $e;
} catch (\Throwable $e) {
$this->incrementLoginAttempts($request);
throw ValidationException::withMessages([
'email' => [__('auth.failed')],
]);
}
$token = $user->createToken('admin');
return [
'user'  => AuthUserResource::make($user),
'token' => $token->plainTextToken,
];
}
}

Поддерживающие файлы

LoginRequest.php

<?php
declare(strict_types=1);
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
final class LoginRequest extends FormRequest
{
public function rules(): array
{
return [
'email'    => ['required', 'email'],
'password' => ['required'],
];
}
public function email(): string
{
return $this->input('email');
}
public function password(): string
{
return $this->input('password');
}
}

Authuserresource.php

<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class AuthUserResource extends JsonResource
{
public function toArray($request): array
{
$this->resource = [
'id'    => $this->resource->id,
'name'  => $this->resource->name,
'email' => $this->resource->email,
];
return parent::toArray($request);
}
}

Шаг 4: Служба аутентификации

Вот как я структурировал свою логику бэкэнд:services → admin → authПолем

Authservice.php

<?php
declare(strict_types = 1);
namespace App\Services\Admin\Auth;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;
final class AuthService
{
public function __construct()
{
}
public function login(string $email, string $password): User
{
$user = $this->findByEmail($email);
throw_if(
!$user || !Hash::check($password, $user->password),
ValidationException::withMessages([
'password' => __('auth.failed'),
])
);
return $user;
}
public function findByEmail(string $email): User|null
{
return User::query()->where('email', $email)->first();
}
}

Limitloginattempts.php

<?php
declare(strict_types=1);
namespace App\Services\Admin\Auth;
use Illuminate\Auth\Events\Lockout;
use Illuminate\Cache\RateLimiter;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use Illuminate\Validation\ValidationException;
use Symfony\Component\HttpFoundation\Response;
trait LimitLoginAttempts
{
public function maxAttempts(): int
{
return property_exists($this, 'maxAttempts') ? $this->maxAttempts : 5;
}
public function decayMinutes(): int
{
return property_exists($this, 'decayMinutes') ? $this->decayMinutes : 1;
}
protected function hasTooManyLoginAttempts(Request $request): bool
{
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request),
$this->maxAttempts()
);
}
protected function incrementLoginAttempts(Request $request): void
{
$this->limiter()->hit(
$this->throttleKey($request),
$this->decayMinutes() * 60
);
}
protected function sendLockoutResponse(Request $request): void
{
$seconds = $this->limiter()->availableIn(
$this->throttleKey($request)
);
throw ValidationException::withMessages([
$this->loginKey() => [__('auth.throttle', [
'seconds' => $seconds,
'minutes' => ceil($seconds / 60),
])],
])->status(Response::HTTP_TOO_MANY_REQUESTS);
}
protected function clearLoginAttempts(Request $request): void
{
$this->limiter()->clear($this->throttleKey($request));
}
protected function limiter(): RateLimiter
{
return app(RateLimiter::class);
}
protected function fireLockoutEvent(Request $request): void
{
event(new Lockout($request));
}
protected function throttleKey(Request $request): string
{
return Str::transliterate(Str::lower($request->input($this->loginKey())) . '|' . $request->ip());
}
protected function loginKey(): string
{
return 'email';
}
}

Шаг 5: Маршруты + посева

маршруты/admin.php

<?php
declare(strict_types = 1);
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\AuthController;
Route::group(['prefix' => 'auth'], function () {
Route::post('login', [AuthController::class, 'login'])->name('login');
Route::group(['middleware' => ['auth:admin']], function () {
Route::post('logout', [AuthController::class, 'logout']);
Route::get('/get-identity', [AuthController::class, 'getIdentity']);
Route::get('/check-auth', [AuthController::class, 'checkAuth']);
});
});

Затем я зарегистрировал его внутриbootstrap/app.php:

Route::middleware('admin')
->prefix('admin')
->group(base_path('routes/admin.php'));

Добавить пользователя семян

Обновлятьdatabase/seeders/DatabaseSeeder.php:

use App\Models\User;
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
public function run(): void
{
User::factory()->create([
'name' => 'Test User',
'email' => 'test@example.com',
'password' => '12345678',
]);
}
}

Затем беги:

php artisan db:seed
composer run dev 

Войдите, используя посевные учетные данные. Если вы попадете в проблему CORS, запустите:

php artisan config:publish cors

Затем обновлениеconfig/cors.php:

'paths' => ['api/*', 'sanctum/csrf-cookie', 'admin/*'],

Ты закончил

На этом этапе у меня был полностью функциональный стек Admiral Laravel + с Auth, ограничивающим скорость и интеграцию фронта. Если вы сделали это так далеко, вы готовы перейти к Cruds, таблицам, мониторингам и всем остальным.

Это для следующей статьи.

Вопросы? Мысли? Я все уши - пинг меня на GitHub или бросьте проблему наАдмиралПолем


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE