Как это устроено:
За аутентификацию отвечает конфиг config/auth.php. Там описаны гарды (guards) и провайдеры (providers). Гард web хранит состояние входа в сессии, провайдер users достаёт пользователей из базы через модель App\Models\User. Для обычного сайта дефолтные настройки менять не нужно.
Модель User и миграция таблицы users идут с фреймворком из коробки, вы их видели в главах 4 и 5. Обратите внимание на метод casts() модели: поле password там объявлено как hashed. При записи в это поле Laravel сам прогонит строку через bcrypt, вызывать Hash::make вручную не нужно.
Регистрация:
Код: Выделить всё
// app/Http/Controllers/Auth/RegisterController.php
use Illuminate\Validation\Rules\Password;
public function store(Request $request)
{
$data = $request->validate([
'name' => ['required', 'string', 'max:255'],
'email' => ['required', 'email', 'unique:users'],
'password' => ['required', 'confirmed', Password::min(8)],
]);
$user = User::create($data);
Auth::login($user);
return redirect()->route('dashboard');
}Вход и выход:
Код: Выделить всё
// app/Http/Controllers/Auth/LoginController.php
public function store(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials, $request->boolean('remember'))) {
$request->session()->regenerate();
return redirect()->intended('/dashboard');
}
return back()->withErrors([
'email' => 'Неверная почта или пароль.',
])->onlyInput('email');
}
public function destroy(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}Маршруты и доступ:
Код: Выделить всё
// routes/web.php
Route::middleware('guest')->group(function () {
Route::get('/login', [LoginController::class, 'create'])->name('login');
Route::post('/login', [LoginController::class, 'store']);
Route::get('/register', [RegisterController::class, 'create'])->name('register');
Route::post('/register', [RegisterController::class, 'store']);
});
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index'])->name('dashboard');
Route::post('/logout', [LoginController::class, 'destroy'])->name('logout');
});Код: Выделить всё
@auth
<span>{{ auth()->user()->name }}</span>
<form method="POST" action="{{ route('logout') }}">
@csrf
<button type="submit">Выйти</button>
</form>
@else
<a href="{{ route('login') }}">Войти</a>
@endauthТипичные грабли:
Двойное хэширование. Если при касте hashed вы ещё и сами вызываете Hash::make, пароль захэшируется дважды и Auth::attempt всегда будет возвращать false. Симптом: регистрация проходит, вход никогда.
Логаут по GET-ссылке. Выход должен быть POST-формой с @csrf, как в примере выше. Иначе чужой сайт сможет разлогинивать ваших пользователей обычным тегом img, а браузерный префетч ссылок будет выкидывать их из аккаунта сам.
Ручное сравнение паролей. Никаких $user->password === $request->password. Только Auth::attempt или Hash::check.
Забытый regenerate. Без перегенерации сессии после входа вы открыты для session fixation, а без regenerateToken после выхода старый CSRF-токен остаётся живым.
Итог:
Вы собрали полный цикл: регистрация с автологином, вход с "запомнить меня", выход и закрытые маршруты. Middleware auth мы пока использовали как чёрный ящик, в следующей главе разберём, как middleware устроены и как писать свои. А сброс пароля по почте дождётся главы про отправку писем и уведомления.