Автентифікація · Laravel
Частину підрозділів ще не перекладено, вони показані англійською нижче в тексті або лишились в оригіналі. Готові фрагменти вже перевірені редактором.
Вступ
Багато вебзастосунків дають користувачам можливість автентифікуватися і «увійти». Реалізація цієї функції буває складною і ризикованою справою. Тому Laravel намагається дати вам інструменти, потрібні для швидкої, безпечної та простої реалізації автентифікації.
В основі засобів автентифікації Laravel лежать «guard» і «provider». Guard визначають, як користувачі автентифікуються для кожного запиту. Наприклад, Laravel постачається з guard session, який зберігає стан через сховище сесій і cookie.
Провайдери (provider) визначають, як користувачі дістаються з вашого постійного сховища. Laravel з коробки підтримує отримання користувачів через Eloquent і конструктор запитів. Проте ви вільні визначати додаткові провайдери відповідно до потреб застосунку.
Конфігураційний файл автентифікації вашого застосунку розташований у config/auth.php. Цей файл містить кілька добре задокументованих опцій для налаштування поведінки сервісів автентифікації Laravel.
Примітка Не плутайте guard і provider з «ролями» та «дозволами». Щоб дізнатися більше про авторизацію дій користувача через дозволи, зверніться до документації з авторизації.
Стартові набори
Хочете почати швидко? Встановіть стартовий набір застосунку Laravel у свіжий застосунок Laravel. Після міграції бази даних перейдіть у браузері на /register або будь-яку іншу URL, призначену вашому застосунку. Стартові набори подбають про створення всієї системи автентифікації!
Навіть якщо ви вирішите не використовувати стартовий набір у фінальному застосунку Laravel, встановлення стартового набору може бути чудовою нагодою навчитися, як реалізувати всю функціональність автентифікації Laravel у реальному проєкті. Оскільки стартові набори Laravel містять контролери, маршрути та представлення (view) для автентифікації, ви можете розібрати код у цих файлах, щоб побачити, як можна реалізувати можливості автентифікації Laravel.
Що врахувати в базі даних
За замовчуванням Laravel містить модель Eloquent App\Models\User у теці app/Models. Цю модель можна використовувати з типовим драйвером автентифікації Eloquent.
Якщо ваш застосунок не використовує Eloquent, ви можете скористатися провайдером автентифікації database, який використовує конструктор запитів Laravel. Якщо ваш застосунок працює з MongoDB, перегляньте офіційну документацію MongoDB про автентифікацію користувачів у Laravel.
Створюючи схему бази даних для моделі App\Models\User, переконайтеся, що колонка пароля має довжину щонайменше 60 символів. Звісно, міграція таблиці users, включена в нові застосунки Laravel, уже створює колонку, довжина якої перевищує це значення.
Також варто перевірити, що ваша таблиця users (чи її аналог) містить nullable-колонку remember_token типу string на 100 символів. Ця колонка використовується для зберігання токена користувачів, які під час входу обрали опцію «запамʼятати мене». Знову ж таки, типова міграція таблиці users, включена в нові застосунки Laravel, уже містить цю колонку.
Огляд екосистеми
Laravel пропонує кілька пакетів, повʼязаних з автентифікацією. Перш ніж рухатися далі, ми розглянемо загальну екосистему автентифікації в Laravel і обговоримо призначення кожного пакета.
Спершу подумайте про те, як працює автентифікація. Використовуючи вебпереглядач, користувач вводить своє імʼя користувача і пароль через форму входу. Якщо ці облікові дані правильні, застосунок збереже інформацію про автентифікованого користувача в сесії користувача. Cookie, видана браузеру, містить ID сесії, щоб наступні запити до застосунку могли повʼязати користувача з правильною сесією. Отримавши cookie сесії, застосунок отримає дані сесії за її ID, побачить, що інформація про автентифікацію збережена в сесії, і вважатиме користувача «автентифікованим».
Коли віддаленому сервісу потрібно автентифікуватися для доступу до API, cookie зазвичай не використовуються, бо немає вебпереглядача. Натомість віддалений сервіс надсилає API-токен до API з кожним запитом. Застосунок може перевірити вхідний токен за таблицею дійсних API-токенів і «автентифікувати» запит як виконаний користувачем, повʼязаним із цим API-токеном.
Вбудовані сервіси браузерної автентифікації Laravel
Laravel містить вбудовані сервіси автентифікації та сесій, до яких зазвичай звертаються через фасади Auth і Session. Ці можливості забезпечують автентифікацію на основі cookie для запитів, що ініційовані вебпереглядачами. Вони надають методи, що дозволяють перевірити облікові дані користувача і автентифікувати його. Крім того, ці сервіси автоматично збережуть відповідні дані автентифікації в сесії користувача і видадуть cookie сесії. Опис того, як користуватися цими сервісами, міститься в цій документації.
Стартові набори застосунку
Як ідеться в цій документації, ви можете взаємодіяти з цими сервісами автентифікації вручну, щоб побудувати власний шар автентифікації застосунку. Проте, щоб допомогти вам стартувати швидше, ми випустили безкоштовні стартові набори, які дають надійну, сучасну заготовку всього шару автентифікації.
Сервіси автентифікації API в Laravel
Laravel пропонує два необовʼязкові пакети, що допомагають керувати API-токенами й автентифікувати запити, зроблені з API-токенами: Passport і Sanctum. Зверніть увагу, що ці бібліотеки і вбудовані бібліотеки автентифікації Laravel на основі cookie не є взаємовиключними. Ці бібліотеки зосереджені переважно на автентифікації за API-токенами, тоді як вбудовані сервіси автентифікації зосереджені на браузерній автентифікації через cookie. Багато застосунків використовуватимуть і вбудовані сервіси автентифікації Laravel на основі cookie, і один з пакетів автентифікації API.
Passport
Passport - це провайдер автентифікації OAuth2, що пропонує різноманітні «grant types» OAuth2, які дозволяють видавати різні типи токенів. Загалом це потужний і складний пакет для автентифікації API. Проте більшість застосунків не потребують складних можливостей специфікації OAuth2, які можуть заплутати і користувачів, і розробників. До того ж розробники історично плуталися в тому, як автентифікувати SPA-застосунки чи мобільні застосунки з використанням провайдерів автентифікації OAuth2 на кшталт Passport.
Sanctum
У відповідь на складність OAuth2 і плутанину серед розробників ми взялися побудувати простіший, більш обтічний пакет автентифікації, який міг би обслуговувати і власні вебзапити з вебпереглядача, і API-запити через токени. Ця мета була реалізована з випуском Laravel Sanctum, який варто вважати бажаним і рекомендованим пакетом автентифікації для застосунків, що пропонують власний вебінтерфейс на додачу до API, або працюють на односторінковому застосунку (SPA), який існує окремо від бекенду Laravel, або застосунків з мобільним клієнтом.
Laravel Sanctum - це гібридний пакет web / API автентифікації, який може керувати всім процесом автентифікації вашого застосунку. Це можливо тому, що коли застосунок на базі Sanctum отримує запит, Sanctum спершу визначить, чи містить запит cookie сесії, яка посилається на автентифіковану сесію. Sanctum робить це, викликаючи вбудовані сервіси автентифікації Laravel, які ми обговорювали раніше. Якщо запит автентифікується не через cookie сесії, Sanctum перевірить запит на наявність API-токена. Якщо API-токен присутній, Sanctum автентифікує запит за цим токеном. Щоб дізнатися більше про цей процес, зверніться до документації Sanctum «how it works».
Підсумок і вибір свого стека
Підсумовуючи: якщо доступ до вашого застосунку відбувається через браузер і ви будуєте монолітний застосунок Laravel, ваш застосунок використовуватиме вбудовані сервіси автентифікації Laravel.
Далі, якщо ваш застосунок пропонує API, яке споживатимуть треті сторони, ви обиратимете між Passport і Sanctum для автентифікації за API-токенами. Загалом Sanctum варто надавати перевагу там, де це можливо, бо він є простим і повним рішенням для автентифікації API, SPA та мобільних застосунків, включно з підтримкою «scopes» чи «abilities».
Якщо ви будуєте односторінковий застосунок (SPA), який працює на бекенді Laravel, вам слід використовувати Laravel Sanctum. З Sanctum вам знадобиться або вручну реалізувати власні маршрути автентифікації на бекенді, або скористатися Laravel Fortify як headless-сервісом автентифікації на бекенді, що надає маршрути й контролери для таких можливостей, як реєстрація, скидання пароля, підтвердження електронної пошти тощо.
Passport можна обрати, коли вашому застосунку абсолютно необхідні всі можливості специфікації OAuth2. Крім того, якщо ви будуєте MCP-сервер, до якого звертатимуться AI-клієнти, вам слід використовувати Passport, бо MCP-клієнти зазвичай очікують автентифікації через OAuth.
А якщо ви хочете почати швидко, ми з радістю рекомендуємо наші стартові набори застосунків як швидкий спосіб почати новий застосунок Laravel, який уже використовує наш бажаний стек автентифікації з вбудованими сервісами Laravel.
Швидкий старт з автентифікацією
Увага Ця частина документації описує автентифікацію користувачів через стартові набори застосунків Laravel, які містять заготовку UI, щоб допомогти вам швидко стартувати. Якщо ви хочете інтегруватися з системами автентифікації Laravel напряму, перегляньте документацію про ручну автентифікацію користувачів.
Встановлення стартового набору
Спершу вам слід встановити стартовий набір застосунку Laravel. Наші стартові набори пропонують гарно оформлені відправні точки для впровадження автентифікації у ваш свіжий застосунок Laravel.
Отримання автентифікованого користувача
Після створення застосунку зі стартового набору й надання користувачам можливості реєструватися та автентифікуватися вам часто доведеться взаємодіяти з поточним автентифікованим користувачем. Під час обробки вхідного запиту ви можете дістатися до автентифікованого користувача через метод user фасаду Auth:
use Illuminate\Support\Facades\Auth;
// Отримати поточного автентифікованого користувача...
$user = Auth::user();
// Отримати ID поточного автентифікованого користувача...
$id = Auth::id();
Крім того, після автентифікації користувача ви можете дістатися до нього через екземпляр Illuminate\Http\Request. Памʼятайте: класи, вказані через type-hint, автоматично впроваджуються у методи вашого контролера. Вказавши type-hint для обʼєкта Illuminate\Http\Request, ви отримаєте зручний доступ до автентифікованого користувача з будь-якого методу контролера вашого застосунку через метод user запиту:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class FlightController extends Controller
{
/**
* Update the flight information for an existing flight.
*/
public function update(Request $request): RedirectResponse
{
$user = $request->user();
// ...
return redirect('/flights');
}
}
Визначення, чи автентифікований поточний користувач
Щоб визначити, чи автентифікований користувач, який робить вхідний HTTP-запит, ви можете скористатися методом check фасаду Auth. Цей метод поверне true, якщо користувач автентифікований:
use Illuminate\Support\Facades\Auth;
if (Auth::check()) {
// Користувач увійшов у систему...
}
Примітка Хоча визначити автентифікованість користувача можна методом
check, зазвичай ви використовуватимете middleware, щоб перевірити автентифікацію користувача перед тим, як надати йому доступ до певних маршрутів / контролерів. Щоб дізнатися більше про це, перегляньте документацію про захист маршрутів.
Захист маршрутів
Middleware маршрутів можна використати, щоб пускати до певного маршруту лише автентифікованих користувачів. Laravel постачається з middleware auth, який є псевдонімом middleware для класу Illuminate\Auth\Middleware\Authenticate. Оскільки Laravel уже реєструє цей псевдонім внутрішньо, вам лишається тільки причепити middleware до визначення маршруту:
Route::get('/flights', function () {
// Лише автентифіковані користувачі можуть звертатися до цього маршруту...
})->middleware('auth');
Перенаправлення неавтентифікованих користувачів
Коли middleware auth виявляє неавтентифікованого користувача, він перенаправляє його на іменований маршрут login. Ви можете змінити цю поведінку методом redirectGuestsTo у файлі bootstrap/app.php вашого застосунку:
use Illuminate\Http\Request;
->withMiddleware(function (Middleware $middleware): void {
$middleware->redirectGuestsTo('/login');
// Із замиканням...
$middleware->redirectGuestsTo(fn (Request $request) => route('login'));
})
Перенаправлення автентифікованих користувачів
Коли middleware guest виявляє автентифікованого користувача, він перенаправляє його на іменований маршрут dashboard або home. Ви можете змінити цю поведінку методом redirectUsersTo у файлі bootstrap/app.php вашого застосунку:
use Illuminate\Http\Request;
->withMiddleware(function (Middleware $middleware): void {
$middleware->redirectUsersTo('/panel');
// Із замиканням...
$middleware->redirectUsersTo(fn (Request $request) => route('panel'));
})
Вказання guard
Причіплюючи middleware auth до маршруту, ви також можете вказати, який «guard» слід використати для автентифікації користувача. Вказаний guard має відповідати одному з ключів масиву guards вашого конфігураційного файлу auth.php:
Route::get('/flights', function () {
// Лише автентифіковані користувачі можуть звертатися до цього маршруту...
})->middleware('auth:admin');
Обмеження спроб входу
Якщо ви використовуєте один з наших стартових наборів застосунків, обмеження частоти автоматично застосовується до спроб входу. За замовчуванням користувач не зможе увійти протягом однієї хвилини, якщо після кількох спроб він не надав правильних облікових даних. Обмеження унікальне для імені користувача / адреси електронної пошти і його IP-адреси.
Примітка Якщо ви хочете обмежити частоту звернень до інших маршрутів вашого застосунку, перегляньте документацію про обмеження частоти.
Ручна автентифікація користувачів
Ви не зобовʼязані використовувати заготовку автентифікації, включену до стартових наборів застосунків Laravel. Якщо ви вирішите не користуватися нею, вам доведеться керувати автентифікацією користувачів безпосередньо через класи автентифікації Laravel. Не хвилюйтеся, це дуже просто!
Ми звертатимемося до сервісів автентифікації Laravel через фасад Auth, тож потрібно імпортувати фасад Auth на початку класу. Далі погляньмо на метод attempt. Метод attempt зазвичай використовується для обробки спроб автентифікації з форми «входу» вашого застосунку. Якщо автентифікація успішна, вам слід згенерувати нову сесію користувача, щоб запобігти фіксації сесії:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller
{
/**
* Handle an authentication attempt.
*/
public function authenticate(Request $request): RedirectResponse
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('dashboard');
}
return back()->withErrors([
'email' => 'The provided credentials do not match our records.',
])->onlyInput('email');
}
}
Метод attempt приймає масив пар ключ / значення як перший аргумент. Значення в масиві використовуються для пошуку користувача в таблиці вашої бази даних. Отже, у прикладі вище користувача буде знайдено за значенням колонки email. Якщо користувача знайдено, хешований пароль, збережений у базі даних, буде порівняно зі значенням password, переданим методу через масив. Вам не слід хешувати значення password з вхідного запиту, оскільки фреймворк автоматично хешує значення перед порівнянням із хешованим паролем у базі даних. Якщо два хешовані паролі збігаються, для користувача розпочнеться автентифікована сесія.
Памʼятайте: сервіси автентифікації Laravel отримують користувачів із вашої бази даних відповідно до конфігурації «provider» вашого guard автентифікації. У типовому конфігураційному файлі config/auth.php вказано провайдер користувачів Eloquent, і йому наказано використовувати модель App\Models\User під час отримання користувачів. Ви можете змінити ці значення у своєму конфігураційному файлі відповідно до потреб застосунку.
Метод attempt поверне true, якщо автентифікація була успішною. Інакше буде повернуто false.
Метод intended, наданий редиректором Laravel, перенаправить користувача на URL, до якої він намагався звернутися перед тим, як його перехопив middleware автентифікації. Цьому методу можна передати запасну URI на випадок, якщо бажаний пункт призначення недоступний.
Вказання додаткових умов
За бажання ви можете додати до запиту автентифікації додаткові умови на додачу до email і пароля користувача. Для цього достатньо додати умови запиту до масиву, переданого методу attempt. Наприклад, ми можемо перевірити, що користувач позначений як «active»:
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
// Автентифікація була успішною...
}
Для складних умов запиту ви можете передати замикання у масиві облікових даних. Це замикання буде викликане з екземпляром запиту, що дозволить вам налаштувати запит відповідно до потреб застосунку:
use Illuminate\Database\Eloquent\Builder;
if (Auth::attempt([
'email' => $email,
'password' => $password,
fn (Builder $query) => $query->has('activeSubscription'),
])) {
// Автентифікація була успішною...
}
Увага У цих прикладах
Метод attemptWhen, який приймає замикання другим аргументом, можна використати для ретельнішої перевірки потенційного користувача перед тим, як фактично його автентифікувати. Замикання отримує потенційного користувача і має повернути true або false, вказуючи, чи можна автентифікувати користувача:
if (Auth::attemptWhen([
'email' => $email,
'password' => $password,
], function (User $user) {
return $user->isNotBanned();
})) {
// Автентифікація була успішною...
}
Доступ до конкретних екземплярів guard
Через метод guard фасаду Auth ви можете вказати, який екземпляр guard хочете використати при автентифікації користувача. Це дозволяє керувати автентифікацією для окремих частин застосунку, використовуючи цілком окремі моделі для автентифікації або таблиці користувачів.
Імʼя guard, передане методу guard, має відповідати одному з guard, налаштованих у вашому конфігураційному файлі auth.php:
if (Auth::guard('admin')->attempt($credentials)) {
// ...
}
Запамʼятовування користувачів
Багато вебзастосунків мають на формі входу чекбокс «запамʼятати мене». Якщо ви хочете реалізувати функціональність «запамʼятати мене» у своєму застосунку, ви можете передати булеве значення другим аргументом методу attempt.
Коли це значення дорівнює true, Laravel триматиме користувача автентифікованим нескінченно або доки він вручну не вийде з системи. Ваша таблиця users має містити рядкову колонку remember_token, яка використовуватиметься для зберігання токена «запамʼятати мене». Міграція таблиці users, включена в нові застосунки Laravel, уже містить цю колонку:
use Illuminate\Support\Facades\Auth;
if (Auth::attempt(['email' => $email, 'password' => $password], $remember)) {
// Користувача запамʼятовують...
}
Якщо ваш застосунок пропонує функціональність «запамʼятати мене», ви можете скористатися методом viaRemember, щоб визначити, чи був поточний автентифікований користувач автентифікований за допомогою cookie «запамʼятати мене»:
use Illuminate\Support\Facades\Auth;
if (Auth::viaRemember()) {
// ...
}
Інші способи автентифікації
Автентифікація екземпляра користувача
Якщо вам потрібно призначити наявний екземпляр користувача поточним автентифікованим користувачем, ви можете передати цей екземпляр методу login фасаду Auth. Переданий екземпляр користувача має бути реалізацією контракту Illuminate\Contracts\Auth\Authenticatable. Модель App\Models\User, що входить до складу Laravel, уже реалізує цей інтерфейс. Цей спосіб автентифікації корисний, коли у вас уже є дійсний екземпляр користувача, наприклад одразу після його реєстрації у вашому застосунку:
use Illuminate\Support\Facades\Auth;
Auth::login($user);
Ви можете передати булеве значення другим аргументом методу login. Це значення вказує, чи потрібна функціональність «запамʼятати мене» для автентифікованої сесії. Памʼятайте, це означає, що сесія буде автентифікованою нескінченно або доки користувач вручну не вийде із застосунку:
Auth::login($user, $remember = true);
За потреби ви можете вказати guard автентифікації перед викликом методу login:
Auth::guard('admin')->login($user);
Автентифікація користувача за ID
Щоб автентифікувати користувача за первинним ключем його запису в базі даних, ви можете скористатися методом loginUsingId. Цей метод приймає первинний ключ користувача, якого ви хочете автентифікувати:
Auth::loginUsingId(1);
Ви можете передати булеве значення в аргумент remember методу loginUsingId. Це значення вказує, чи потрібна функціональність «запамʼятати мене» для автентифікованої сесії. Памʼятайте, це означає, що сесія буде автентифікованою нескінченно або доки користувач вручну не вийде із застосунку:
Auth::loginUsingId(1, remember: true);
Одноразова автентифікація користувача
Ви можете скористатися методом once, щоб автентифікувати користувача в застосунку на один-єдиний запит. Під час виклику цього методу сесії та cookie не використовуються, а подія Login не буде відправлена:
if (Auth::once($credentials)) {
// ...
}
HTTP Basic Authentication
HTTP Basic Authentication дає швидкий спосіб автентифікувати користувачів вашого застосунку без окремої сторінки «входу». Щоб почати, причепіть middleware auth.basic до маршруту. Middleware auth.basic входить до складу фреймворку Laravel, тож визначати його не потрібно:
Route::get('/profile', function () {
// Лише автентифіковані користувачі можуть звертатися до цього маршруту...
})->middleware('auth.basic');
Щойно middleware причеплений до маршруту, при зверненні до маршруту в браузері ви автоматично отримаєте запит облікових даних. За замовчуванням middleware auth.basic вважає, що колонка email у вашій таблиці users є «іменем користувача».
Зауваження щодо FastCGI
Якщо ви використовуєте PHP FastCGI і Apache для обслуговування свого застосунку Laravel, HTTP Basic authentication може працювати некоректно. Щоб виправити ці проблеми, до файлу .htaccess вашого застосунку можна додати такі рядки:
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
HTTP Basic Authentication без стану
Ви також можете використовувати HTTP Basic Authentication без встановлення cookie з ідентифікатором користувача в сесії. Це насамперед корисно, якщо ви вирішили автентифікувати запити до API вашого застосунку через HTTP Authentication. Для цього визначте middleware, який викликає метод onceBasic. Якщо метод onceBasic не повертає відповіді, запит можна передати далі в застосунок:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\Response;
class AuthenticateOnceWithBasicAuth
{
/**
* Handle an incoming request.
*
* @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next
*/
public function handle(Request $request, Closure $next): Response
{
return Auth::onceBasic() ?: $next($request);
}
}
Далі причепіть middleware до маршруту:
Route::get('/api/user', function () {
// Лише автентифіковані користувачі можуть звертатися до цього маршруту...
})->middleware(AuthenticateOnceWithBasicAuth::class);
Вихід із системи
Щоб вручну вивести користувачів із застосунку, ви можете скористатися методом logout фасаду Auth. Це прибере інформацію про автентифікацію з сесії користувача, тож наступні запити не будуть автентифікованими.
Крім виклику методу logout, рекомендується скасувати сесію користувача і згенерувати новий CSRF-токен. Після виходу користувача ви зазвичай перенаправите його на корінь вашого застосунку:
use Illuminate\Http\Request;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
/**
* Log the user out of the application.
*/
public function logout(Request $request): RedirectResponse
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}
Скасування сесій на інших пристроях
Laravel також надає механізм скасування і «виходу» для сесій користувача, активних на інших пристроях, без скасування сесії на його поточному пристрої. Ця можливість зазвичай використовується, коли користувач змінює або оновлює свій пароль і ви хочете скасувати сесії на інших пристроях, зберігши автентифікацію на поточному.
Перш ніж почати, переконайтеся, що middleware Illuminate\Session\Middleware\AuthenticateSession підключений до маршрутів, які мають отримувати автентифікацію сесії. Зазвичай цей middleware розміщують у визначенні групи маршрутів, щоб він застосовувався до більшості маршрутів вашого застосунку. За замовчуванням middleware AuthenticateSession можна причепити до маршруту через псевдонім middleware auth.session:
Route::middleware(['auth', 'auth.session'])->group(function () {
Route::get('/', function () {
// ...
});
});
Далі ви можете скористатися методом logoutOtherDevices фасаду Auth. Цей метод вимагає, щоб користувач підтвердив свій поточний пароль, який ваш застосунок має прийняти через форму вводу:
use Illuminate\Support\Facades\Auth;
Auth::logoutOtherDevices($currentPassword);
Коли метод logoutOtherDevices викликано, інші сесії користувача будуть повністю скасовані, тобто він «вийде» з усіх guard, якими раніше був автентифікований.
Підтвердження пароля
Під час розробки застосунку у вас час від часу траплятимуться дії, які мають вимагати від користувача підтвердження пароля перед виконанням дії або перед перенаправленням користувача до чутливої частини застосунку. Laravel містить вбудований middleware, який робить цей процес простим. Реалізація цієї функціональності вимагатиме від вас визначити два маршрути: один для показу представлення (view) із проханням підтвердити пароль, і другий для перевірки, що пароль дійсний, і перенаправлення користувача до бажаного пункту призначення.
Примітка Наступна документація описує, як інтегруватися з можливостями підтвердження пароля Laravel безпосередньо; проте, якщо ви хочете почати швидше, стартові набори застосунків Laravel містять підтримку цієї функції!
Конфігурація
Після підтвердження пароля користувача не проситимуть підтвердити його знову протягом трьох годин. Проте ви можете налаштувати проміжок часу до повторного запиту пароля, змінивши значення конфігурації password_timeout у конфігураційному файлі config/auth.php вашого застосунку.
Маршрутизація
Форма підтвердження пароля
Спершу ми визначимо маршрут для показу представлення (view), що просить користувача підтвердити свій пароль:
Route::get('/confirm-password', function () {
return view('auth.confirm-password');
})->middleware('auth')->name('password.confirm');
Як і слід очікувати, представлення (view), що повертається цим маршрутом, має містити форму з полем password. Крім того, можете додати у представлення текст, що пояснює: користувач входить до захищеної частини застосунку і має підтвердити свій пароль.
Підтвердження пароля
Далі ми визначимо маршрут, який оброблятиме запит форми з представлення «confirm password». Цей маршрут відповідатиме за валідацію пароля і перенаправлення користувача до бажаного пункту призначення:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
Route::post('/confirm-password', function (Request $request) {
if (! Hash::check($request->password, $request->user()->password)) {
return back()->withErrors([
'password' => ['The provided password does not match our records.']
]);
}
$request->session()->passwordConfirmed();
return redirect()->intended();
})->middleware(['auth', 'throttle:6,1']);
Перш ніж рухатися далі, розгляньмо цей маршрут докладніше. Спочатку перевіряється, чи поле password із запиту дійсно збігається з паролем автентифікованого користувача. Якщо пароль дійсний, нам треба повідомити сесію Laravel, що користувач підтвердив свій пароль. Метод passwordConfirmed встановить у сесії користувача мітку часу, за якою Laravel зможе визначити, коли користувач востаннє підтверджував пароль. Нарешті, ми можемо перенаправити користувача до бажаного пункту призначення.
Захист маршрутів
Вам слід переконатися, що будь-якому маршруту, який виконує дію, що вимагає нещодавнього підтвердження пароля, призначено middleware password.confirm. Цей middleware входить до типової інсталяції Laravel і автоматично збереже бажаний пункт призначення користувача в сесії, щоб користувача можна було перенаправити туди після підтвердження пароля. Зберігши бажаний пункт призначення в сесії, middleware перенаправить користувача на іменований маршрут password.confirm:
Route::get('/settings', function () {
// ...
})->middleware(['password.confirm']);
Route::post('/settings', function () {
// ...
})->middleware(['password.confirm']);
Додавання власних guard
Ви можете визначити власні guard автентифікації методом extend фасаду Auth. Виклик методу extend слід розмістити у сервіс-провайдері. Оскільки Laravel уже постачається з AppServiceProvider, ми можемо розмістити код у цьому провайдері:
<?php
namespace App\Providers;
use App\Services\Auth\JwtGuard;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::extend('jwt', function (Application $app, string $name, array $config) {
// Повернути екземпляр Illuminate\Contracts\Auth\Guard...
return new JwtGuard(Auth::createUserProvider($config['provider']));
});
}
}
Як видно з прикладу вище, колбек, переданий методу extend, має повернути реалізацію Illuminate\Contracts\Auth\Guard. Цей інтерфейс містить кілька методів, які вам треба буде реалізувати, щоб визначити власний guard. Щойно ваш власний guard визначено, ви можете посилатися на нього в конфігурації guards вашого файлу auth.php:
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
Guard на основі замикання та запиту
Найпростіший спосіб реалізувати власну систему автентифікації на основі HTTP-запиту - це метод Auth::viaRequest. Він дозволяє швидко описати ваш процес автентифікації одним замиканням.
Щоб почати, викличте метод Auth::viaRequest у методі boot вашого AppServiceProvider. Метод viaRequest приймає імʼя драйвера автентифікації першим аргументом. Це імʼя може бути будь-яким рядком, що описує ваш власний guard. Другим аргументом методу передається замикання, яке отримує вхідний HTTP-запит і повертає екземпляр користувача або, якщо автентифікація не вдалася, null:
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::viaRequest('custom-token', function (Request $request) {
return User::where('token', (string) $request->token)->first();
});
}
Щойно ваш власний драйвер автентифікації визначено, ви можете налаштувати його як драйвер у конфігурації guards вашого файлу auth.php:
'guards' => [
'api' => [
'driver' => 'custom-token',
],
],
Нарешті, ви можете посилатися на цей guard, призначаючи middleware автентифікації маршруту:
Route::middleware('auth:api')->group(function () {
// ...
});
Додавання власних провайдерів користувачів
Якщо ви не використовуєте традиційну реляційну базу даних для зберігання користувачів, вам треба буде розширити Laravel власним провайдером користувачів для автентифікації. Ми скористаємося методом provider фасаду Auth, щоб визначити власний провайдер користувачів. Резолвер провайдера користувачів має повернути реалізацію Illuminate\Contracts\Auth\UserProvider:
<?php
namespace App\Providers;
use App\Extensions\MongoUserProvider;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
// ...
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Auth::provider('mongo', function (Application $app, array $config) {
// Повернути екземпляр Illuminate\Contracts\Auth\UserProvider...
return new MongoUserProvider($app->make('mongo.connection'));
});
}
}
Після реєстрації провайдера методом provider ви можете перемкнутися на новий провайдер користувачів у конфігураційному файлі auth.php. Спершу визначте provider, що використовує ваш новий драйвер:
'providers' => [
'users' => [
'driver' => 'mongo',
],
],
Нарешті, ви можете посилатися на цей провайдер у конфігурації guards:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
Контракт User Provider
Реалізації Illuminate\Contracts\Auth\UserProvider відповідають за вилучення реалізації Illuminate\Contracts\Auth\Authenticatable із системи постійного зберігання, як-от MySQL, MongoDB тощо. Ці два інтерфейси дозволяють механізмам автентифікації Laravel працювати незалежно від того, як зберігаються дані користувачів і який тип класу представляє автентифікованого користувача:
Погляньмо на контракт Illuminate\Contracts\Auth\UserProvider:
<?php
namespace Illuminate\Contracts\Auth;
interface UserProvider
{
public function retrieveById($identifier);
public function retrieveByToken($identifier, $token);
public function updateRememberToken(Authenticatable $user, $token);
public function retrieveByCredentials(array $credentials);
public function validateCredentials(Authenticatable $user, array $credentials);
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false);
}
Функція retrieveById зазвичай отримує ключ, що представляє користувача, наприклад автоінкрементний ID з бази даних MySQL. Метод має знайти й повернути реалізацію Authenticatable, що відповідає цьому ID.
Функція retrieveByToken отримує користувача за його унікальним $identifier і токеном $token для «запамʼятати мене», який зазвичай зберігається в колонці бази даних на кшталт remember_token. Як і в попередньому методі, цей метод має повернути реалізацію Authenticatable із відповідним значенням токена.
Метод updateRememberToken оновлює remember_token екземпляра $user новим значенням $token. Свіжий токен призначається користувачам при успішній спробі автентифікації через «запамʼятати мене» або коли користувач виходить із системи.
Метод retrieveByCredentials отримує масив облікових даних, переданих методу Auth::attempt під час спроби автентифікації в застосунку. Далі метод має «запитати» базове постійне сховище про користувача, що відповідає цим обліковим даним. Зазвичай цей метод виконає запит з умовою «where», що шукає запис користувача з «username», який збігається зі значенням $credentials['username']. Метод має повернути реалізацію Authenticatable. Цей метод не повинен намагатися виконувати жодної валідації пароля чи автентифікації.
Метод validateCredentials має порівняти переданого $user із $credentials, щоб автентифікувати користувача. Наприклад, цей метод зазвичай використовує метод Hash::check, щоб порівняти значення $user->getAuthPassword() зі значенням $credentials['password']. Метод має повернути true або false, вказуючи, чи пароль дійсний.
Метод rehashPasswordIfRequired має перехешувати пароль переданого $user, якщо це потрібно і підтримується. Наприклад, цей метод зазвичай використовує метод Hash::needsRehash, щоб визначити, чи значення $credentials['password'] потребує перехешування. Якщо пароль треба перехешувати, метод має використати метод Hash::make для перехешування пароля і оновити запис користувача в базовому постійному сховищі.
Контракт Authenticatable
Тепер, коли ми розглянули кожен з методів UserProvider, погляньмо на контракт Authenticatable. Памʼятайте: провайдери користувачів мають повертати реалізації цього інтерфейсу з методів retrieveById, retrieveByToken і retrieveByCredentials:
<?php
namespace Illuminate\Contracts\Auth;
interface Authenticatable
{
public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPasswordName();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}
Цей інтерфейс простий. Метод getAuthIdentifierName має повернути назву колонки «первинного ключа» користувача, а метод getAuthIdentifier - сам «первинний ключ» користувача. У випадку з MySQL це, найімовірніше, буде автоінкрементний первинний ключ, призначений запису користувача. Метод getAuthPasswordName має повернути назву колонки пароля користувача. Метод getAuthPassword має повернути хешований пароль користувача.
Цей інтерфейс дозволяє системі автентифікації працювати з будь-яким класом «користувача», незалежно від того, який ORM чи шар абстракції сховища ви використовуєте. За замовчуванням Laravel містить клас App\Models\User у теці app/Models, який реалізує цей інтерфейс.
Автоматичне перехешування паролів
Типовий алгоритм хешування паролів у Laravel - bcrypt. «Work factor» для хешів bcrypt можна налаштувати через конфігураційний файл config/hashing.php вашого застосунку або змінну середовища BCRYPT_ROUNDS.
Неперекладені підрозділи, які лишилися в оригіналі англійською: решта розділу «Automatic Password Rehashing» (опис автоматичного перехешування при зміні work factor і опція rehash_on_login), а також «Events».
Перекладаємо з офіційної документації, розділ за розділом, і не ховаємо недоперекладене. Помітили неточність у терміні чи реченні: напишіть, виправимо.