1. Безопасность
  2. Аутентификация

Введение

Многие веб-приложения предоставляют пользователям возможность аутентификации в приложении и "входа" в систему. Реализация этой функции в веб-приложениях может быть сложной и потенциально рискованной задачей. По этой причине Laravel стремится предоставить вам инструменты, необходимые для быстрой, безопасной и простой реализации аутентификации.

По своей сути средства аутентификации Laravel состоят из "стражей" и "поставщиков". Стражи определяют, как пользователи аутентифицируются для каждого запроса. Например, Laravel поставляется со стражем session, который поддерживает состояние с использованием сессионного хранилища и файлов cookie.

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

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

Примечание Сторожи и поставщики не следует путать с "ролями" и "разрешениями". Чтобы узнать больше о авторизации действий пользователя с использованием разрешений, обратитесь к документации по авторизации.

Стартовые комплекты

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

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

Аспекты базы данных

По умолчанию Laravel включает модель Eloquent App\Models\User в вашем каталоге app/Models. Эта модель может использоваться с оригинальным драйвером аутентификации Eloquent. Если ваше приложение не использует Eloquent, вы можете использовать поставщик аутентификации database, который использует построитель запросов Laravel.

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

Также убедитесь, что в вашей таблице users (или эквивалентной) есть столбец remember_token типа string с возможностью нулевого значения и длиной 100 символов. Этот столбец будет использоваться для хранения токена для пользователей, выбравших опцию "запомнить меня" при входе в ваше приложение. Снова отметим, что миграция таблицы users, включенная в новые приложения Laravel, уже содержит этот столбец.

Обзор экосистемы

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

Сначала рассмотрим, как работает аутентификация. При использовании веб-браузера пользователь предоставляет свое имя пользователя и пароль через форму входа. Если эти учетные данные верны, приложение сохранит информацию об аутентифицированном пользователе в сессии. Cookie, отправленный в браузер, содержит идентификатор сеанса, чтобы последующие запросы к приложению могли ассоциировать пользователя с правильной сессией. После получения cookie сессии приложение извлечет данные сессии на основе идентификатора сессии, отметит, что информация об аутентификации сохранена в сессии, и будет рассматривать пользователя как "аутентифицированного".

Когда удаленный сервис должен аутентифицироваться для доступа к API, обычно не используются файлы cookie, так как нет веб-браузера. Вместо этого удаленный сервис отправляет токен API на API при каждом запросе. Приложение может проверить входящий токен по таблице действительных токенов API и "аутентифицировать" запрос как выполненный пользователем, связанным с этим токеном API.

Встроенные в Laravel службы аутентификации браузера

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

Application Starter Kits

Как обсуждается в этой документации, вы можете взаимодействовать с этими службами аутентификации вручную, чтобы создать собственный уровень аутентификации вашего приложения. Однако, чтобы помочь вам начать быстрее, мы выпустили бесплатные пакеты, которые предоставляют крепкую, современную каркас всего уровня аутентификации. Эти пакеты: Laravel Breeze, Laravel Jetstream и Laravel Fortify.

Laravel Breeze - это простая, минимальная реализация всех функций аутентификации Laravel, включая вход, регистрацию, сброс пароля, подтверждение электронной почты и подтверждение пароля. Представление Laravel Breeze состоит из простых шаблонов Blade, стилизованных с использованием Tailwind CSS. Для начала ознакомьтесь с документацией по начальным комплектам приложений Laravel.

Laravel Fortify - это бэкенд аутентификации для Laravel, реализующий многие функции, о которых говорится в этой документации, включая аутентификацию на основе файлов cookie, а также другие функции, такие как двухфакторная аутентификация и подтверждение электронной почты. Fortify предоставляет бэкенд аутентификации для Laravel Jetstream или может использоваться независимо в сочетании с Laravel Sanctum для предоставления аутентификации для SPA, которое должно аутентифицироваться с Laravel.

Laravel Jetstream - это крепкий набор инструментов для запуска приложения, который потребляет и предоставляет службы аутентификации Laravel Fortify с красивым, современным пользовательским интерфейсом, созданным с использованием Tailwind CSS, Livewire и / или Inertia. Laravel Jetstream включает дополнительную поддержку двухфакторной аутентификации, поддержку команд, управление сеансами браузера, управление профилем и встроенную интеграцию с Laravel Sanctum для предоставления аутентификации по токену API. Предложения Laravel по аутентификации через API обсуждаются ниже.

Службы аутентификации API Laravel

Laravel предоставляет два дополнительных пакета, которые помогут вам управлять токенами API и аутентификацией запросов, выполненных с использованием токенов API: Passport и Sanctum. Пожалуйста, обратите внимание, что эти библиотеки и встроенные библиотеки аутентификации на основе файлов cookie в Laravel не являются взаимоисключающими. Эти библиотеки в первую очередь сосредотачиваются на аутентификации по токену API, в то время как встроенные службы аутентификации сосредотачиваются на аутентификации в браузере с использованием файлов cookie. Многие приложения будут использовать как встроенные службы аутентификации Laravel на основе файлов cookie, так и один из пакетов аутентификации 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 Sanctum - это пакет API, который мы выбрали для включения в стартовый комплект приложения Laravel Jetstream, потому что мы считаем, что он лучше всего подходит для большинства потребностей в аутентификации веб-приложений.

Итоги и выбор вашего стека

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

Затем, если ваше приложение предоставляет API, которое будет использоваться третьими сторонами, вы выберете между Passport или Sanctum для предоставления аутентификации по токену API для вашего приложения. В целом, Sanctum следует предпочитать, поскольку это простое, полное решение для аутентификации API, аутентификации SPA и аутентификации мобильных устройств, включая поддержку "scopes" или "abilities".

Если вы создаете одностраничное приложение (SPA), которое будет работать на бэкенде Laravel, вы должны использовать Laravel Sanctum. При использовании Sanctum вам придется вручную реализовать свои маршруты аутентификации на бэкенде или использовать Laravel Fortify в качестве бэкенд-сервиса аутентификации без пользовательского интерфейса, предоставляющего маршруты и контроллеры для таких функций, как регистрация, сброс пароля, верификация электронной почты и многое другое.

Passport может быть выбран, когда ваше приложение абсолютно нуждается во всех функциях, предоставляемых спецификацией OAuth2.

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

Быстрый старт в аутентификацию

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

Установить стартовый комплект

Во-первых, вам следует установить стартовый комплект приложения Laravel. Наши текущие стартовые комплекты, Laravel Breeze и Laravel Jetstream, предлагают красиво оформленные отправные точки для внедрения аутентификации в ваше новое приложение Laravel.

Laravel Breeze - это минимальная, простая реализация всех функций аутентификации Laravel, включая вход, регистрацию, сброс пароля, верификацию электронной почты и подтверждение пароля. Визуальный слой Laravel Breeze состоит из простых шаблонов Blade, стилизованных с использованием Tailwind CSS. Кроме того, Breeze предоставляет опции для создания каркасов на основе Livewire или Inertia, с возможностью выбора Vue или React для каркасов на основе Inertia.

Laravel Jetstream - это более мощный стартовый комплект приложения, который включает поддержку создания каркаса для вашего приложения с использованием Livewire или Inertia и Vue. Кроме того, Jetstream поддерживает двухфакторную аутентификацию, команды, управление профилем, управление сеансами браузера, поддержку API через Laravel Sanctum, удаление учетной записи и многое другое.

Получение аутентифицированного пользователя

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

use Illuminate\Support\Facades\Auth;
 
// Получить текущего аутентифицированного пользователя...
$user = Auth::user();
 
// Получить идентификатор текущего аутентифицированного пользователя...
$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, обычно для проверки аутентификации пользователя перед предоставлением доступа к определенным маршрутам/контроллерам вы будете использовать промежуточное ПО. Чтобы узнать больше об этом, ознакомьтесь с документацией по защите маршрутов.

Защита маршрутов

Промежуточное ПО маршрута можно использовать, чтобы разрешить доступ только аутентифицированным пользователям к определенному маршруту. Laravel поставляется с промежуточным ПО auth, которое ссылается на класс Illuminate\Auth\Middleware\Authenticate. Поскольку это промежуточное ПО уже зарегистрировано в ядре HTTP вашего приложения, вам нужно всего лишь присоединить промежуточное ПО к определению маршрута:

Route::get('/flights', function () {
// Доступ к этому маршруту разрешен только аутентифицированным пользователям...
})->middleware('auth');

Перенаправление неаутентифицированных пользователей

Когда промежуточное ПО auth обнаруживает неаутентифицированного пользователя, оно перенаправит пользователя на именованный маршрут login. Вы можете изменить это поведение, обновив функцию redirectTo в файле app/Http/Middleware/Authenticate.php вашего приложения:

use Illuminate\Http\Request;
 
/**
* Получить путь, на который пользователь должен быть перенаправлен.
*/
protected function redirectTo(Request $request): string
{
return route('login');
}

Указание стража

При присоединении промежуточного ПО auth к маршруту вы также можете указать, какой "сторож" должен использоваться для аутентификации пользователя. Указанный сторож должен соответствовать одному из ключей массива guards в вашем файле конфигурации auth.php:

Route::get('/flights', function () {
// Доступ к этому маршруту разрешен только аутентифицированным пользователям...
})->middleware('auth:admin');

Ограничение входа

Если вы используете стартовые комплекты Laravel Breeze или Laravel Jetstream starter kits, ограничение количества попыток входа в систему будет автоматически применяться. По умолчанию пользователь не сможет войти в систему в течение одной минуты, если несколько раз подряд предоставит неверные учетные данные. Защита от перебора уникальна для имени пользователя / адреса электронной почты пользователя и его IP-адреса.

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

Ручная аутентификация пользователей

Вы не обязаны использовать каркас аутентификации, включенный в стартовые комплекты приложений Laravel. Если вы решите не использовать этот каркас, вам придется управлять аутентификацией пользователей непосредственно с использованием классов аутентификации Laravel. Не волнуйтесь, это просто!

Мы будем использовать службы аутентификации Laravel через фасад Auth facade, поэтому нам нужно убедиться, что мы импортируем фасад 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' => 'Предоставленные учетные данные не совпадают с нашими записями.',
])->onlyInput('email');
}
}

Метод attempt принимает массив пар ключ / значение в качестве своего первого аргумента. Значения в массиве будут использоваться для поиска пользователя в вашей таблице базы данных. Таким образом, в приведенном выше примере пользователь будет извлечен по значению столбца email. Если пользователь найден, хешированный пароль, сохраненный в базе данных, будет сравниваться с значением password, переданным методу через массив. Вы не должны хешировать значение password входящего запроса, поскольку фреймворк автоматически хеширует значение перед сравнением его с хешированным паролем в базе данных. Для пользователя будет начата аутентифицированная сессия, если два хешированных пароля совпадут.

Помните, что службы аутентификации Laravel будут извлекать пользователей из вашей базы данных на основе конфигурации "поставщика" вашей аутентификационной стражи. В конфигурационном файле по умолчанию config/auth.php указан поставщик пользователей Eloquent, и ему указано использовать модель App\Models\User при извлечении пользователей. Вы можете изменить эти значения в вашем файле конфигурации в зависимости от потребностей вашего приложения.

Метод attempt вернет true, если аутентификация прошла успешно. В противном случае будет возвращено false.

Метод intended, предоставляемый перенаправителем Laravel, перенаправит пользователя по URL, который он пытался посетить перед перехватом промежуточного программного обеспечения аутентификации. Заглушка URI может быть предоставлена этому методу, если предполагаемое место назначения недоступно.

Указание дополнительных условий

Если хотите, вы также можете добавить дополнительные условия запроса к запросу аутентификации, кроме электронной почты и пароля пользователя. Для этого мы можем просто добавить условия запроса к массиву, переданному методу attempt. Например, мы можем проверить, что пользователь отмечен как "активный":

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 фасада Auth вы можете указать, какой экземпляр стража вы хотели бы использовать при аутентификации пользователя. Это позволяет управлять аутентификацией для отдельных частей вашего приложения с использованием полностью отдельных моделей аутентификации или таблиц пользователей.

Имя стража, переданное методу 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);

При необходимости вы можете указать страж аутентификации перед вызовом метода login:

Auth::guard('admin')->login($user);

Аутентификация пользователя по идентификатору

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

Auth::loginUsingId(1);

Вы можете передать логическое значение вторым аргументом методу loginUsingId. Это значение указывает, требуется ли функционал "запомнить меня" для аутентифицированной сессии. Помните, что это означает, что сеанс будет аутентифицирован бессрочно или до тех пор, пока пользователь не выйдет из системы вручную:

Auth::loginUsingId(1, $remember = true);

Аутентификация пользователя однократно

Вы можете использовать метод once, чтобы аутентифицировать пользователя в приложении для одного запроса. При вызове этого метода сеансы или файлы cookie не будут использоваться:

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

HTTP-аутентификация по базовому протоколу

HTTP-аутентификация по базовому принципу предоставляет быстрый способ аутентификации пользователей вашего приложения без настройки отдельной страницы "входа". Для начала прикрепите промежуточное ПО auth.basic к маршруту. Промежуточное ПО auth.basic включено в Laravel по умолчанию, поэтому вам не нужно его определять:

Route::get('/profile', function () {
// Доступ к этому маршруту разрешен только аутентифицированным пользователям...
})->middleware('auth.basic');

После того как промежуточное ПО будет прикреплено к маршруту, вас автоматически попросят ввести учетные данные при доступе к маршруту в вашем браузере. По умолчанию промежуточное ПО auth.basic будет считать, что столбец email в вашей таблице базы данных users является "именем пользователя" пользователя.

Примечание к FastCGI

Если вы используете PHP FastCGI и Apache для обслуживания вашего приложения Laravel, HTTP-аутентификация по базовому принципу может не работать правильно. Чтобы исправить эти проблемы, следующие строки могут быть добавлены в файл .htaccess вашего приложения:

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

Безсостоятельная HTTP-аутентификация по базовому протоколу

Вы также можете использовать HTTP-аутентификацию по базовому принципу без установки идентификатора пользователя в сессии. Это в первую очередь полезно, если вы решите использовать HTTP-аутентификацию для аутентификации запросов к API вашего приложения. Для этого определите промежуточное ПО, которое вызывает метод 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);
}
 
}

Затем прикрепите промежуточное ПО к маршруту:

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 также предоставляет механизм аннулирования и "выхода" из сеансов пользователя на других устройствах без аннулирования сеанса на их текущем устройстве. Эта функция обычно используется, когда пользователь меняет или обновляет свой пароль, и вы хотели бы аннулировать сеансы на других устройствах, сохраняя при этом аутентификацию на текущем устройстве.

Прежде чем начать, убедитесь, что промежуточное ПО Illuminate\Session\Middleware\AuthenticateSession включено на маршрутах, которые должны принимать аутентификацию сеанса. Обычно его следует разместить в определении группы маршрутов, чтобы оно могло применяться к большинству маршрутов вашего приложения. По умолчанию промежуточное ПО AuthenticateSession может быть прикреплено к маршруту с использованием псевдонима промежуточного ПО маршрута auth.session, как определено в HTTP-ядре вашего приложения:

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

Затем вы можете использовать метод logoutOtherDevices, предоставленный фасадом Auth. Этот метод требует от пользователя подтвердить свой текущий пароль, который ваше приложение должно принимать через форму ввода:

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

Когда вызывается метод logoutOtherDevices, другие сеансы пользователя будут аннулированы полностью, что означает, что они будут "выходить" из всех стражей, от которых они были ранее аутентифицированы.

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

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

Примечание Следующая документация рассматривает интеграцию с прямыми возможностями подтверждения пароля 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. Это промежуточное ПО включено в стандартную установку Laravel и автоматически сохраняет намеченное место пользователя в сеансе, чтобы пользователя можно было перенаправить на это место после подтверждения пароля. После сохранения намеченного места пользователя в сеансе промежуточное ПО перенаправит пользователя на именованный маршрут password.confirm:

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

Добавление собственных стражей

Вы можете определить свои собственные стражи аутентификации с использованием метода extend фасада Auth. Вы должны разместить вызов метода extend в поставщике служб. Поскольку Laravel уже поставляется с AuthServiceProvider, мы можем поместить код в этот провайдер:

<?php
 
namespace App\Providers;
 
use App\Services\Auth\JwtGuard;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
 
class AuthServiceProvider 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. Этот интерфейс содержит несколько методов, которые вам нужно реализовать для определения собственного стража. После того как ваш собственный страж будет определен, вы можете ссылаться на него в конфигурации стражей вашего файла конфигурации auth.php:

'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],

Сторожевые стражи запросов

Простейший способ реализации собственной системы аутентификации на основе HTTP-запроса - использование метода Auth::viaRequest. Этот метод позволяет быстро определить процесс аутентификации с использованием всего лишь одного замыкания.

Чтобы начать, вызовите метод Auth::viaRequest в методе boot вашего AuthServiceProvider. Метод viaRequest принимает имя драйвера аутентификации в качестве своего первого аргумента. Это имя может быть любой строкой, описывающей ваш собственный страж. Вторым аргументом, передаваемым методу, должно быть замыкание, которое принимает входящий 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();
});
}

После того как ваш собственный драйвер аутентификации будет определен, вы можете настроить его как драйвер в конфигурации стражей вашего файла конфигурации auth.php:

'guards' => [
'api' => [
'driver' => 'custom-token',
],
],

Наконец, вы можете ссылаться на страж при назначении промежуточного ПО аутентификации для маршрута:

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\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Auth;
 
class AuthServiceProvider 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);
}

Функция retrieveById обычно получает ключ, представляющий пользователя, например, автоинкрементный ID из базы данных MySQL. Метод должен извлечь и вернуть реализацию Authenticatable, соответствующую этому ID.

Функция retrieveByToken извлекает пользователя по его уникальному $identifier и токену "запомнить" $token, обычно хранящемуся в столбце базы данных, например, remember_token. Как и в предыдущем методе, этот метод должен возвращать реализацию Authenticatable с соответствующим значением токена.

Метод updateRememberToken обновляет remember_token экземпляра $user новым $token. Новый токен назначается пользователям при успешной попытке аутентификации с "запомнить меня" или при выходе пользователя.

Метод retrieveByCredentials получает массив учетных данных, переданный методу Auth::attempt при попытке аутентификации в приложении. Затем метод должен "запросить" постоянное хранилище наличие пользователя, соответствующего этим учетным данным. Обычно этот метод будет выполнять запрос с условием "where", который ищет запись пользователя с "именем пользователя", совпадающим со значением $credentials['username']. Метод должен возвращать реализацию Authenticatable. Этот метод не должен выполнять проверку пароля или аутентификацию.

Метод validateCredentials должен сравнивать данный $user с $credentials для аутентификации пользователя. Например, этот метод обычно будет использовать метод Hash::check для сравнения значения $user->getAuthPassword() со значением $credentials['password']. Этот метод должен возвращать true или false, указывая, действительный ли пароль.

Контракт аутентифицируемого

Теперь, когда мы рассмотрели каждый из методов UserProvider, давайте посмотрим на контракт Authenticatable. Помните, что провайдеры пользователей должны возвращать реализации этого интерфейса из методов retrieveById, retrieveByToken и retrieveByCredentials:

<?php
 
namespace Illuminate\Contracts\Auth;
 
interface Authenticatable
{
public function getAuthIdentifierName();
public function getAuthIdentifier();
public function getAuthPassword();
public function getRememberToken();
public function setRememberToken($value);
public function getRememberTokenName();
}

Этот интерфейс прост. Метод getAuthIdentifierName должен возвращать имя поля "первичного ключа" пользователя, а метод getAuthIdentifier должен возвращать "первичный ключ" пользователя. При использовании бэкенда MySQL это, вероятно, будет автоинкрементный первичный ключ, назначенный записи пользователя. Метод getAuthPassword должен возвращать хешированный пароль пользователя.

Этот интерфейс позволяет системе аутентификации работать с любым классом "пользователя", независимо от того, какую ORM или слой абстракции хранения вы используете. По умолчанию Laravel включает класс App\Models\User в каталоге app/Models, который реализует этот интерфейс.

События

Laravel отправляет различные события во время процесса аутентификации. Вы можете прикреплять слушателей к этим событиям в своем EventServiceProvider:

/**
* Сопоставление обработчиков событий для приложения.
*
* @var array
*/
protected $listen = [
'Illuminate\Auth\Events\Registered' => [
'App\Listeners\LogRegisteredUser',
],
 
'Illuminate\Auth\Events\Attempting' => [
'App\Listeners\LogAuthenticationAttempt',
],
 
'Illuminate\Auth\Events\Authenticated' => [
'App\Listeners\LogAuthenticated',
],
 
'Illuminate\Auth\Events\Login' => [
'App\Listeners\LogSuccessfulLogin',
],
 
'Illuminate\Auth\Events\Failed' => [
'App\Listeners\LogFailedLogin',
],
 
'Illuminate\Auth\Events\Validated' => [
'App\Listeners\LogValidated',
],
 
'Illuminate\Auth\Events\Verified' => [
'App\Listeners\LogVerified',
],
 
'Illuminate\Auth\Events\Logout' => [
'App\Listeners\LogSuccessfulLogout',
],
 
'Illuminate\Auth\Events\CurrentDeviceLogout' => [
'App\Listeners\LogCurrentDeviceLogout',
],
 
'Illuminate\Auth\Events\OtherDeviceLogout' => [
'App\Listeners\LogOtherDeviceLogout',
],
 
'Illuminate\Auth\Events\Lockout' => [
'App\Listeners\LogLockout',
],
 
'Illuminate\Auth\Events\PasswordReset' => [
'App\Listeners\LogPasswordReset',
],
];