Autenticació
Els fonaments de l'autenticació a Laravel: guards, providers, login manual, remember me i protegir rutes.
Com funciona l'autenticació#
El sistema d'autenticació de Laravel es basa en dos conceptes: guards i providers. Un guard defineix com s'autentiquen els usuaris per a cada petició. Per exemple, el guard session utilitza cookies de sessió per identificar l'usuari, mentre que el guard token utilitza un token a la capçalera de la petició. Un provider defineix d'on es recuperen els usuaris: normalment d'una taula de la base de dades amb Eloquent.
Configuració#
La configuració d'autenticació es troba a config/auth.php. Per defecte, Laravel configura un guard web basat en sessions i un provider users que utilitza el model User:
// config/auth.php
'defaults' => [
'guard' => 'web',
'passwords' => 'users',
],
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
],El guard web utilitza sessions PHP per mantenir l'estat d'autenticació entre peticions. El provider users utilitza Eloquent per recuperar els usuaris de la taula users. Pots afegir guards addicionals per a diferents tipus d'usuaris o mecanismes d'autenticació.
Múltiples guards#
Si la teva aplicació té diferents tipus d'usuaris (per exemple, clients i administradors), pots crear guards separats:
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
],Per utilitzar un guard específic:
// Autenticar amb el guard admin
Auth::guard('admin')->attempt($credentials);
// Obtenir l'usuari del guard admin
$admin = Auth::guard('admin')->user();Autenticació manual#
Tot i que els starter kits com Breeze i Jetstream proporcionen una implementació completa, és important entendre com funciona l'autenticació manualment.
Login#
El mètode attempt() comprova les credencials contra la base de dades. Si la contrasenya coincideix, crea una sessió autenticada:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
public function login(Request $request)
{
$credentials = $request->validate([
'email' => ['required', 'email'],
'password' => ['required'],
]);
if (Auth::attempt($credentials)) {
$request->session()->regenerate();
return redirect()->intended('dashboard');
}
return back()->withErrors([
'email' => 'Les credencials no coincideixen amb els nostres registres.',
])->onlyInput('email');
}El mètode regenerate() regenera l'ID de sessió per prevenir atacs de fixació de sessió. El mètode intended() redirigeix l'usuari a la URL que intentava visitar abans de ser redirigit al login, o a l'URL per defecte si no n'hi havia cap.
Pots afegir condicions addicionals a l'intent d'autenticació:
// Només usuaris actius
if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => true])) {
// Login correcte
}Remember me#
Per mantenir l'usuari autenticat entre sessions del navegador, passa true com a segon paràmetre d'attempt():
if (Auth::attempt($credentials, $request->boolean('remember'))) {
// L'usuari es mantindrà autenticat
}Això crea un token de "remember me" a la base de dades i una cookie persistent al navegador. La taula users necessita la columna remember_token (que ve per defecte a la migració d'usuaris de Laravel).
Logout#
public function logout(Request $request)
{
Auth::logout();
$request->session()->invalidate();
$request->session()->regenerateToken();
return redirect('/');
}La seqüència és important: primer tanques la sessió d'autenticació, després invalides la sessió HTTP i finalment regeneres el token CSRF. Això garanteix que la sessió queda completament netejada i protegida.
Autenticar una instància d'usuari#
Si ja tens una instància del model User (per exemple, després d'un registre), pots autenticar-la directament:
// Login directe amb un model User
Auth::login($user);
// Login amb remember me
Auth::login($user, remember: true);
// Login per ID
Auth::loginUsingId(1);Accedir a l'usuari autenticat#
Hi ha diverses maneres d'obtenir l'usuari autenticat:
use Illuminate\Support\Facades\Auth;
// Amb la facade Auth
$user = Auth::user();
$id = Auth::id();
// Des de la petició
$user = $request->user();
// Comprovar si està autenticat
if (Auth::check()) {
// L'usuari ha iniciat sessió
}
// Comprovar si és un convidat (no autenticat)
if (Auth::guest()) {
// No està autenticat
}A les vistes Blade, pots utilitzar les directives @auth i @guest:
@auth
<p>Hola, {{ auth()->user()->name }}!</p>
<form method="POST" action="/logout">
@csrf
<button type="submit">Tancar sessió</button>
</form>
@endauth
@guest
<a href="/login">Iniciar sessió</a>
<a href="/register">Registrar-se</a>
@endguestSi tens múltiples guards:
@auth('admin')
<p>Ets un administrador</p>
@endauthProtegir rutes#
El middleware auth redirigeix els usuaris no autenticats al formulari de login:
// Ruta individual
Route::get('/dashboard', function () {
return view('dashboard');
})->middleware('auth');
// Grup de rutes
Route::middleware('auth')->group(function () {
Route::get('/dashboard', [DashboardController::class, 'index']);
Route::get('/profile', [ProfileController::class, 'edit']);
Route::resource('articles', ArticleController::class);
});Per redirigir a una ruta específica en lloc del login per defecte, personalitza el middleware al fitxer bootstrap/app.php:
->withMiddleware(function (Middleware $middleware) {
$middleware->redirectGuestsTo('/login');
})Protegir amb un guard específic#
Route::middleware('auth:admin')->group(function () {
Route::get('/admin/dashboard', [AdminController::class, 'index']);
});Confirmació de contrasenya#
Per a accions sensibles (canviar el correu, eliminar el compte), pots requerir que l'usuari confirmi la seva contrasenya abans de continuar:
Route::get('/settings', function () {
// L'usuari ha de confirmar la contrasenya
})->middleware(['auth', 'password.confirm']);Quan l'usuari visita una ruta amb aquest middleware, Laravel el redirigeix a un formulari de confirmació de contrasenya. Un cop confirmada, l'usuari pot accedir a la ruta durant un temps configurable (per defecte, 3 hores).
Limitar intents de login#
Per protegir contra atacs de força bruta, pots limitar els intents de login amb el trait ThrottlesLogins o manualment amb el RateLimiter:
use Illuminate\Support\Facades\RateLimiter;
public function login(Request $request)
{
$throttleKey = Str::lower($request->email) . '|' . $request->ip();
if (RateLimiter::tooManyAttempts($throttleKey, 5)) {
$seconds = RateLimiter::availableIn($throttleKey);
return back()->withErrors([
'email' => "Massa intents. Torna a provar-ho d'aquí {$seconds} segons.",
]);
}
if (Auth::attempt($request->only('email', 'password'))) {
RateLimiter::clear($throttleKey);
$request->session()->regenerate();
return redirect()->intended('dashboard');
}
RateLimiter::hit($throttleKey, 60); // Bloquejar durant 60 segons
return back()->withErrors([
'email' => 'Les credencials no coincideixen.',
]);
}Hashing de contrasenyes#
Laravel utilitza bcrypt per defecte per hashear les contrasenyes. Mai guardis una contrasenya en text pla:
use Illuminate\Support\Facades\Hash;
// Hashear una contrasenya
$hashed = Hash::make('secret');
// Verificar una contrasenya contra un hash
if (Hash::check('secret', $hashedPassword)) {
// La contrasenya coincideix
}
// Comprovar si cal rehashear (si l'algorisme o els rounds han canviat)
if (Hash::needsRehash($hashedPassword)) {
$newHash = Hash::make('secret');
}El model User de Laravel hasheja automàticament la contrasenya gràcies al cast hashed:
protected function casts(): array
{
return [
'password' => 'hashed',
];
}