Автентифікація

Вступ

Багато веб-застосунків надають спосіб для своїх користувачів аутентифікуватися в застосунку та "увійти". Реалізація цієї функції у веб-застосунках може бути складним і потенційно ризикованим завданням. З цієї причини Laravel прагне надати вам інструменти, необхідні для швидкої, безпечної та легкої реалізації аутентифікації.

У своїй основі, засоби аутентифікації Laravel складаються з "охоронців" і "постачальників". Охоронці визначають, як користувачі аутентифікуються для кожного запиту. Наприклад, Laravel постачається з охоронцем session, який підтримує стан, використовуючи зберігання сесій і кукі.

Провайдери визначають, як користувачі отримуються з вашого постійного сховища. Laravel постачається з підтримкою отримання користувачів за допомогою Eloquent та конструктора запитів до бази даних. Однак ви можете вільно визначати додаткові провайдери за потреби для вашого застосунку.

Файл конфігурації автентифікації вашого застосунку знаходиться за адресою config/auth.php. Цей файл містить кілька добре задокументованих опцій для налаштування поведінки сервісів автентифікації Laravel.

Охоронці та провайдери не повинні плутатися з "ролями" та "дозволами". Щоб дізнатися більше про авторизацію дій користувача через дозволи, будь ласка, зверніться до документації з авторизації.

Стартові комплекти

Бажаєте швидко розпочати? Встановіть стартовий набір застосунку Laravel у новому застосунку Laravel. Після міграції вашої бази даних, перейдіть у вашому браузері на /register або будь-яку іншу URL-адресу, призначену вашому застосунку. Стартові набори подбають про створення всієї вашої системи автентифікації!

Навіть якщо ви вирішите не використовувати стартовий комплект у вашому фінальному Laravel-застосунку, встановлення стартового комплекту може бути чудовою можливістю дізнатися, як реалізувати всю функціональність аутентифікації Laravel у реальному проекті Laravel. Оскільки стартові комплекти Laravel містять контролери аутентифікації, маршрути та представлення для вас, ви можете переглянути код у цих файлах, щоб дізнатися, як можуть бути реалізовані функції аутентифікації Laravel.

Міркування щодо бази даних

За замовчуванням Laravel включає App\Models\User Eloquent модель у вашому каталозі app/Models. Ця модель може використовуватися з драйвером автентифікації Eloquent за замовчуванням.

Якщо ваш застосунок не використовує Eloquent, ви можете використовувати провайдер автентифікації database, який використовує конструктор запитів Laravel. Якщо ваш застосунок використовує MongoDB, перегляньте офіційну документацію з автентифікації користувачів Laravel для MongoDB.

Коли створюєте схему бази даних для моделі App\Models\User, переконайтеся, що стовпець пароля має довжину щонайменше 60 символів. Звісно, міграція таблиці users, яка включена в нові застосунки Laravel, вже створює стовпець, що перевищує цю довжину.

Також, ви повинні переконатися, що ваша таблиця users (або еквівалентна) містить стовпець remember_token типу string, який допускає значення NULL, довжиною 100 символів. Цей стовпець буде використовуватися для зберігання токена для користувачів, які обирають опцію "запам'ятати мене" при вході в ваш застосунок. Знову ж таки, стандартна міграція таблиці users, яка включена в нові застосунки Laravel, вже містить цей стовпець.

Огляд екосистеми

Laravel пропонує кілька пакетів, пов'язаних з аутентифікацією. Перш ніж продовжити, ми розглянемо загальну екосистему аутентифікації в Laravel і обговоримо призначення кожного пакета.

Спочатку розгляньте, як працює автентифікація. Під час використання веб-браузера користувач надає своє ім'я користувача та пароль через форму входу. Якщо ці облікові дані правильні, застосунок зберігає інформацію про автентифікованого користувача в сесії користувача. Файл cookie, виданий браузеру, містить ідентифікатор сесії, щоб наступні запити до застосунку могли асоціювати користувача з правильною сесією. Після отримання cookie сесії, застосунок отримає дані сесії на основі ідентифікатора сесії, зазначить, що інформація про автентифікацію була збережена в сесії, і вважатиме користувача "автентифікованим".

Коли віддалений сервіс потребує автентифікації для доступу до API, кукі зазвичай не використовуються для автентифікації, оскільки немає веб-браузера. Натомість віддалений сервіс надсилає API токен до API з кожним запитом. Застосунок може перевірити вхідний токен проти таблиці дійсних API токенів і "автентифікувати" запит як виконаний користувачем, пов'язаним з цим API токеном.

Вбудовані сервіси аутентифікації браузера Laravel

Laravel включає вбудовані служби аутентифікації та сесій, які зазвичай доступні через фасади Auth та Session. Ці функції забезпечують аутентифікацію на основі cookie для запитів, що ініціюються з веб-браузерів. Вони надають методи, які дозволяють перевірити облікові дані користувача та аутентифікувати користувача. Крім того, ці служби автоматично зберігатимуть відповідні дані аутентифікації в сесії користувача та видаватимуть cookie сесії користувача. Обговорення того, як використовувати ці служби, міститься в цій документації.

Стартові комплекти застосунків

Як обговорювалося в цій документації, ви можете взаємодіяти з цими службами автентифікації вручну, щоб створити власний шар автентифікації вашого застосунку. Однак, щоб допомогти вам швидше розпочати, ми випустили безкоштовні стартові набори, які забезпечують надійне, сучасне каркасування всього шару автентифікації.

Служби аутентифікації API в Laravel

Laravel надає два додаткові пакети, які допомагають вам керувати API токенами та аутентифікувати запити, зроблені з API токенами: Passport та Sanctum. Зверніть увагу, що ці бібліотеки та вбудовані бібліотеки аутентифікації на основі cookie у Laravel не є взаємовиключними. Ці бібліотеки в основному зосереджені на аутентифікації за допомогою API токенів, тоді як вбудовані сервіси аутентифікації зосереджені на аутентифікації браузера на основі cookie. Багато застосунків використовуватимуть як вбудовані сервіси аутентифікації на основі cookie у Laravel, так і один з пакетів аутентифікації API у Laravel.

Passport

Passport є провайдером аутентифікації OAuth2, що пропонує різноманітні "типи грантів" OAuth2, які дозволяють видавати різні типи токенів. Загалом, це надійний і складний пакет для аутентифікації API. Однак, більшість застосунків не потребують складних функцій, які пропонує специфікація OAuth2, що може бути заплутаним як для користувачів, так і для розробників. Крім того, розробники історично були збентежені тим, як аутентифікувати SPA-застосунки або мобільні застосунки, використовуючи провайдери аутентифікації OAuth2, такі як Passport.

Sanctum

У відповідь на складність OAuth2 та плутанину розробників, ми вирішили створити простіший, більш оптимізований пакет аутентифікації, який міг би обробляти як запити від першої сторони з веб-браузера, так і API-запити через токени. Ця мета була реалізована з релізом Laravel Sanctum, який слід вважати кращим і рекомендованим пакетом аутентифікації для застосунків, які будуть пропонувати веб-інтерфейс першої сторони на додаток до API, або будуть працювати на основі односторінкового застосунку (SPA), що існує окремо від бекенду Laravel-застосунку, або застосунків, які пропонують мобільний клієнт.

Laravel Sanctum - це гібридний пакет автентифікації для веб / API, який може керувати всім процесом автентифікації вашого застосунку. Це можливо, тому що коли застосунки на базі Sanctum отримують запит, Sanctum спочатку визначає, чи включає запит сесійну cookie, яка посилається на автентифіковану сесію. Sanctum досягає цього, викликаючи вбудовані сервіси автентифікації Laravel, про які ми говорили раніше. Якщо запит не автентифікується через сесійну cookie, Sanctum перевірить запит на наявність API токена. Якщо API токен присутній, Sanctum автентифікує запит, використовуючи цей токен. Щоб дізнатися більше про цей процес, будь ласка, зверніться до документації Sanctum "як це працює".

Резюме та Вибір Вашого Стеку

У підсумку, якщо ваш застосунок буде доступний за допомогою браузера і ви створюєте монолітний Laravel застосунок, ваш застосунок використовуватиме вбудовані служби автентифікації Laravel.

Далі, якщо ваш застосунок пропонує API, яке буде використовуватися третіми сторонами, ви оберете між Passport або Sanctum для забезпечення аутентифікації API токенів для вашого застосунку. Загалом, слід надавати перевагу Sanctum, коли це можливо, оскільки це просте, повне рішення для аутентифікації API, аутентифікації SPA та мобільної аутентифікації, включаючи підтримку "scopes" або "abilities".

Якщо ви створюєте односторінковий застосунок (SPA), який буде працювати на бекенді Laravel, вам слід використовувати Laravel Sanctum. Використовуючи Sanctum, вам потрібно буде або вручну реалізувати власні маршрути аутентифікації на бекенді, або використовувати Laravel Fortify як безголовий сервіс аутентифікації на бекенді, що надає маршрути та контролери для таких функцій, як реєстрація, скидання пароля, верифікація електронної пошти та інше.

Passport може бути обраний, коли вашому застосунку абсолютно необхідні всі функції, надані специфікацією OAuth2.

І, якщо ви хочете швидко розпочати, ми раді рекомендувати наші стартові набори для застосунків як швидкий спосіб розпочати новий застосунок Laravel, який вже використовує нашу рекомендовану аутентифікаційну систему вбудованих сервісів аутентифікації Laravel.

Швидкий старт аутентифікації

Ця частина документації обговорює автентифікацію користувачів через стартові набори застосунків Laravel, які включають шаблони інтерфейсу для швидкого початку роботи. Якщо ви хочете інтегруватися безпосередньо з системами автентифікації Laravel, перегляньте документацію про ручну автентифікацію користувачів.

Встановлення стартового комплекту

Спочатку вам слід встановити стартовий комплект застосунку Laravel. Наші стартові комплекти пропонують чудово оформлені початкові точки для впровадження автентифікації у ваш новий застосунок Laravel.

Отримання автентифікованого користувача

Після створення застосунку з початкового набору та надання користувачам можливості реєструватися та автентифікуватися у вашому застосунку, вам часто потрібно буде взаємодіяти з поточним автентифікованим користувачем. Під час обробки вхідного запиту ви можете отримати доступ до автентифікованого користувача через метод user фасаду Auth:

use Illuminate\Support\Facades\Auth;
 
// Отримати поточного автентифікованого користувача...
$user = Auth::user();
 
// Отримати ID поточного автентифікованого користувача...
$id = Auth::id();

Альтернативно, після автентифікації користувача, ви можете отримати доступ до автентифікованого користувача через екземпляр Illuminate\Http\Request. Пам'ятайте, що класи з підказками типів будуть автоматично впроваджені у ваші методи контролера. Використовуючи підказку типу для об'єкта Illuminate\Http\Request, ви можете зручно отримати доступ до автентифікованого користувача з будь-якого методу контролера у вашому застосунку через метод user запиту:

<?php
 
namespace App\Http\Controllers;
 
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
 
class FlightController extends Controller
{
/**
* Оновити інформацію про рейс для наявного рейсу.
*/
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 постачається з auth middleware, яке є псевдонімом middleware для класу Illuminate\Auth\Middleware\Authenticate. Оскільки це middleware вже має псевдонім у Laravel, все, що вам потрібно зробити, це прикріпити middleware до визначення маршруту:

Route::get('/flights', function () {
// Лише автентифіковані користувачі можуть отримати доступ до цього маршруту...
})->middleware('auth');

Перенаправлення неавтентифікованих користувачів

Коли middleware auth виявляє неавтентифікованого користувача, він перенаправить користувача на login іменований маршрут. Ви можете змінити цю поведінку, використовуючи метод redirectGuestsTo у файлі bootstrap/app.php вашого застосунку:

use Illuminate\Http\Request;
 
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo('/login');
 
// Використовуючи замикання...
$middleware->redirectGuestsTo(fn (Request $request) => route('login'));
})

Перенаправлення автентифікованих користувачів

Коли guest middleware виявляє автентифікованого користувача, він перенаправить користувача на маршрут з іменем dashboard або home. Ви можете змінити цю поведінку, використовуючи метод redirectUsersTo у файлі bootstrap/app.php вашого застосунку:

use Illuminate\Http\Request;
 
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectUsersTo('/panel');
 
// Використовуючи замикання...
$middleware->redirectUsersTo(fn (Request $request) => route('panel'));
})

Вказання Guard

Коли ви додаєте auth middleware до маршруту, ви також можете вказати, який "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
{
/**
* Обробити спробу автентифікації.
*/
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 на випадок, якщо призначене місце призначення недоступне.

Вказання Додаткових Умов

Якщо ви бажаєте, ви також можете додати додаткові умови запиту до запиту автентифікації на додаток до електронної пошти та пароля користувача. Щоб досягти цього, ми можемо просто додати умови запиту до масиву, переданого методу 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'),
])) {
// Автентифікація пройшла успішно...
}

У цих прикладах email не є обов'язковою опцією, це лише приклад. Ви повинні використовувати будь-яке ім'я стовпця, яке відповідає "ім'я користувача" у вашій таблиці бази даних.

Метод 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 для автентифікації користувача в застосунку для одного запиту. Сесії або cookies не будуть використовуватися при виклику цього методу:

if (Auth::once($credentials)) {
    // ...
}

HTTP Базова Аутентифікація

HTTP Basic Authentication надає швидкий спосіб аутентифікації користувачів вашого застосунку без налаштування спеціальної сторінки "входу". Щоб почати, прикріпіть auth.basic middleware до маршруту. auth.basic middleware включено в Laravel фреймворк, тому вам не потрібно його визначати:

Route::get('/profile', function () {
    // Тільки автентифіковані користувачі можуть отримати доступ до цього маршруту...
})->middleware('auth.basic');

Після того, як middleware було прикріплено до маршруту, ви автоматично будете запитуватися про облікові дані при доступі до маршруту у вашому браузері. За замовчуванням, middleware auth.basic буде вважати, що стовпець email у вашій таблиці бази даних users є "ім'ям користувача" користувача.

Примітка щодо FastCGI

Якщо ви використовуєте PHP FastCGI та Apache для обслуговування вашого Laravel застосунку, HTTP Basic аутентифікація може не працювати правильно. Щоб виправити ці проблеми, наступні рядки можуть бути додані до файлу .htaccess вашого застосунку:

RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

Базова HTTP-автентифікація без збереження стану

Ви також можете використовувати базову HTTP-аутентифікацію без встановлення файлу cookie ідентифікатора користувача в сесії. Це особливо корисно, якщо ви вирішите використовувати HTTP-аутентифікацію для аутентифікації запитів до API вашого застосунку. Щоб досягти цього, визначте 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
{
/**
* Обробити вхідний запит.
*
* @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;
 
/**
 * Вийти з застосунку.
 */
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 може бути прикріплено до маршруту, використовуючи auth.session псевдонім middleware:

Route::middleware(['auth', 'auth.session'])->group(function () {
    Route::get('/', function () {
        // ...
    });
});

Потім, ви можете використовувати метод logoutOtherDevices, наданий фасадом Auth. Цей метод вимагає від користувача підтвердити свій поточний пароль, який ваш застосунок повинен прийняти через форму введення:

use Illuminate\Support\Facades\Auth;
 
Auth::logoutOtherDevices($currentPassword);

Коли викликається метод logoutOtherDevices, інші сесії користувача будуть повністю анульовані, що означає, що вони будуть "вийшли" з усіх охоронців, за якими вони раніше були автентифіковані.

Підтвердження пароля

Під час створення вашого застосунку, іноді можуть виникати дії, які вимагають від користувача підтвердити свій пароль перед виконанням дії або перед перенаправленням користувача до чутливої області застосунку. Laravel включає вбудоване middleware, щоб зробити цей процес легким. Реалізація цієї функції вимагатиме від вас визначити два маршрути: один маршрут для відображення представлення, яке просить користувача підтвердити свій пароль, і інший маршрут для підтвердження, що пароль є дійсним, і перенаправлення користувача до їхнього призначеного місця.

Наступна документація обговорює, як інтегруватися з функціями підтвердження пароля Laravel безпосередньо; однак, якщо ви хочете почати швидше, стартові набори застосунків Laravel включають підтримку цієї функції!

Конфігурація

Після підтвердження свого пароля користувач не буде запитуватись про підтвердження пароля знову протягом трьох годин. Однак, ви можете налаштувати тривалість часу до повторного запиту пароля, змінивши значення конфігурації password_timeout у файлі конфігурації config/auth.php вашого застосунку.

Маршрутизація

Форма підтвердження пароля

Спочатку ми визначимо маршрут для відображення представлення, яке запитує у користувача підтвердження пароля:

Route::get('/confirm-password', function () {
    return view('auth.confirm-password');
})->middleware('auth')->name('password.confirm');

Як ви могли очікувати, представлення, яке повертається цим маршрутом, повинно містити форму з полем password. Крім того, не соромтеся включати текст у представлення, який пояснює, що користувач входить у захищену область застосунку і повинен підтвердити свій пароль.

Підтвердження пароля

Далі ми визначимо маршрут, який оброблятиме запит форми з представлення "підтвердити пароль". Цей маршрут буде відповідальним за перевірку пароля та перенаправлення користувача до його запланованого місця призначення:

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Redirect;
 
Route::post('/confirm-password', function (Request $request) {
if (! Hash::check($request->password, $request->user()->password)) {
return back()->withErrors([
'password' => ['Наданий пароль не відповідає нашим даним.']
]);
}
 
$request->session()->passwordConfirmed();
 
return redirect()->intended();
})->middleware(['auth', 'throttle:6,1']);

Перш ніж продовжити, давайте розглянемо цей маршрут детальніше. Спочатку визначається, чи поле запиту password дійсно відповідає паролю автентифікованого користувача. Якщо пароль дійсний, нам потрібно повідомити сесію Laravel, що користувач підтвердив свій пароль. Метод passwordConfirmed встановить мітку часу в сесії користувача, яку Laravel може використовувати для визначення, коли користувач востаннє підтвердив свій пароль. Нарешті, ми можемо перенаправити користувача до його запланованого місця призначення.

Захист маршрутів

Ви повинні переконатися, що будь-який маршрут, який виконує дію, що вимагає підтвердження пароля, призначений для password.confirm middleware. Це middleware включено в стандартну установку Laravel і автоматично зберігатиме заплановане місце призначення користувача в сесії, щоб користувач міг бути перенаправлений до цього місця після підтвердження свого пароля. Після збереження запланованого місця призначення користувача в сесії, middleware перенаправить користувача до password.confirm іменованого маршруту:

Route::get('/settings', function () {
    // ...
})->middleware(['password.confirm']);
 
Route::post('/settings', function () {
    // ...
})->middleware(['password.confirm']);

Додавання Користувацьких Охоронців

Ви можете визначити власні механізми аутентифікації, використовуючи метод 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
{
// ...
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
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',
    ],
],

Захисники запитів на основі замикань

Найпростіший спосіб реалізувати власну систему автентифікації на основі HTTP-запитів — це використання методу Auth::viaRequest. Цей метод дозволяє швидко визначити процес автентифікації за допомогою одного замикання.

Щоб почати, викличте метод Auth::viaRequest у методі boot вашого застосунку AppServiceProvider. Метод viaRequest приймає ім'я драйвера автентифікації як свій перший аргумент. Це ім'я може бути будь-яким рядком, що описує ваш власний guard. Другий аргумент, переданий методу, повинен бути замиканням, яке отримує вхідний HTTP-запит і повертає екземпляр користувача або, якщо автентифікація не вдалася, null:

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
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
{
// ...
 
/**
* Ініціалізувати будь-які сервіси застосунку.
*/
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',
    ],
],

Контракт Провайдера Користувачів

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 повинен повертати хешований пароль користувача.

Цей інтерфейс дозволяє системі аутентифікації працювати з будь-яким класом "user", незалежно від того, який ORM або шар абстракції зберігання ви використовуєте. За замовчуванням Laravel включає клас App\Models\User у директорії app/Models, який реалізує цей інтерфейс.

Автоматичне Перехешування Паролів

Алгоритм хешування паролів за замовчуванням у Laravel - це bcrypt. "Фактор роботи" для хешів bcrypt можна налаштувати через файл конфігурації вашого застосунку config/hashing.php або змінну середовища BCRYPT_ROUNDS.

Зазвичай, коефіцієнт роботи bcrypt слід збільшувати з часом, оскільки обчислювальна потужність CPU / GPU зростає. Якщо ви збільшуєте коефіцієнт роботи bcrypt для вашого застосунку, Laravel плавно та автоматично перехешує паролі користувачів, коли користувачі автентифікуються у вашому застосунку через стартові набори Laravel або коли ви вручну автентифікуєте користувачів за допомогою методу attempt.

Зазвичай автоматичне перехешування паролів не повинно порушувати роботу вашого застосунку; однак, ви можете вимкнути цю поведінку, опублікувавши файл конфігурації hashing:

php artisan config:publish hashing

Після того як файл конфігурації було опубліковано, ви можете встановити значення конфігурації rehash_on_login на false:

'rehash_on_login' => false,

Події

Laravel виконує різноманітні події під час процесу автентифікації. Ви можете визначити слухачів для будь-якої з наступних подій:

Назва події
Illuminate\Auth\Events\Registered
Illuminate\Auth\Events\Attempting
Illuminate\Auth\Events\Authenticated
Illuminate\Auth\Events\Login
Illuminate\Auth\Events\Failed
Illuminate\Auth\Events\Validated
Illuminate\Auth\Events\Verified
Illuminate\Auth\Events\Logout
Illuminate\Auth\Events\CurrentDeviceLogout
Illuminate\Auth\Events\OtherDeviceLogout
Illuminate\Auth\Events\Lockout
Illuminate\Auth\Events\PasswordReset