See changes in Laravel 5.3: https://josephsilber.com/posts/2016/07/10/authentication-improvements-in-laravel-5-3
Per tal de poder activar un sistema d'autenticació és requereix configurar prèviament els proveïdors d'usuaris i els Guards (vegeu fitxer config/auth.php):
La configuració es realitza al fitxer config/auth.php:
https://github.com/laravel/laravel/blob/master/config/auth.php
La configuració per defecte és:
Recursos:
Laravel ofereix per defecte un sistema d'autenticació complet amb les següents funcionalitats:
Si voleu saber com s'han implementat aquestes funcionalitats llegiu l'article:
PHP Notification app. Laravel from scratch
Aquestes funcionalitats formen part del que es coneix com estructura bàsica de Laravel o Scaffolding. Aquesta estructura bàsica conté migracions, model, lògica de negoci i vistes per implementar algunes de les funcionalitats més habituals a una aplicació. Entre d'altres s'ofereix la funcionalitat d'authenticació, Bootstrap less, etc. Podeu optar per no utilitzar aquestes funcionalitats amb la comanda php artisan fresh
Si esteu buscant com controlar permisos i rols d'usuaris consulteu Laravel Authorization
Vegeu un pas a pas a:
http://www.codetutorial.io/laravel-5-rest-api-basic-authentication/
Hi ha tres esdeviments que Laravel dispara durant l'autenticació:
Per crear un gestor de l'esdeveniment auth.login:
$ php artisan handler:event AuthLoginEventHandler Handler created successfully.
Això us crea el fitxer App\Handlers\Events\AuthLoginEventHandler i s'ha de modificar de la següent forma:
<?php namespace App\Handlers\Events; use App\User; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Contracts\Queue\ShouldBeQueued; class AuthLoginEventHandler { /** * Create the event handler. * * @return void */ public function __construct() { // } /** * Handle the event. * * @param User $user * @param $remember * @return void */ public function handle(User $user, $remember) { dd($user); } }
De moment és un exemple per comprovar l'esdeveniment que el que farà és aturar la aplicació un cop el login és correcte i mostrar les dades del usuari logat.
El mètode handle respon a la línia (458 --acacha (discussió) 12:55, 29 abr 2015 (CEST)) del fitxer vendor/laravel/framework/src/Illuminate/Auth/Guard.php:
$this->events->fire('auth.login', [$user, $remember]);
Ara cal realacionar al fitxer:
app\Providers\EventServiceProvider
el handler amb l'esdeveniment:
... protected $listen = [ 'event.name' => [ 'EventListener', ], 'auth.login' => [ 'App\Handlers\Events\AuthLoginEventHandler', ], ]; ...
I recompilar:
$ php artisan clear-compiled
Ara comproveu que després de fer un login us apareix quelcom similar a:
User {#190 ▼ #table: "users" #fillable: array:3 [▶] #hidden: array:2 [▶] #connection: null #primaryKey: "id" #perPage: 15 +incrementing: true +timestamps: true #attributes: array:7 [▶] #original: array:7 [▶] #relations: [] #visible: [] #appends: [] #guarded: array:1 [▶] #dates: [] #casts: [] #touches: [] #observables: [] #with: [] #morphClass: null +exists: true }
Un exemple més habitual es voler afegir variables de sessió després del login i/o monitoritzar l'últim cop que l'usuari es va logar:
Tingueu en compte que cal afegir una migració per al camp last_login
$ php artisan make:migration add_last_login_field_to_users_table
I editeu el fitxer database/migrations/***_add_last_login_field_to_users_table:
<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class AddLastLoginFieldToUsersTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::table('users', function(Blueprint $table) { $table->timestamp('last_login'); }); } /** * Reverse the migrations. * * @return void */ public function down() { // Schema::table('users', function(Blueprint $table) { $table->dropColumn( 'last_login' ); }); } }
Consulteu que teniu una migració pendent:
$ homestead ssh $ cd ~/Code/laravel_base_app $ php artisan migrate:status +------+-------------------------------------------------------+ | Ran? | Migration | +------+-------------------------------------------------------+ | Y | 2014_10_12_000000_create_users_table | | Y | 2014_10_12_100000_create_password_resets_table | | N | 2015_04_29_110559_add_last_login_field_to_users_table | +------+-------------------------------------------------------+
i executeu la migració:
$ php artisan migrate
Resources:
Amb:
$data = Session::all(); dd($data);
Dins de qualsevol controlador un cop autenticat l'usuari us donarà un resultat similar a:
array:5 [▼ "_token" => "SVwym5n72rzxb11FR8JPIP175rD6y1Jd2YXacnc" "_previous" => array:1 [▼ "url" => "http://laravel.app/home" ] "flash" => array:2 [▼ "old" => [] "new" => [] ] "url" => array:1 [▼ "intended" => "http://laravel.app/home" ] "login_82e5d2c56bdd0811318f0cf078b78bfc" => 1 ]
La variable de sessió:
login_82e5d2c56bdd0811318f0cf078b78bfc
Conté el id de l'usuari logat (a l'exemple l'usuari amb id igual a 1)
El codi del framewok Laravel el podeu trobar a:
Illuminate\Auth\Guard
De fet si feu un hash md5 del text Illuminate\Auth\Guard el resultat és:
82e5d2c56bdd0811318f0cf078b78bfc
Per tant per comprovar si hi ha un usuari logat només cal buscar si existeix la variable de sessió
login_82e5d2c56bdd0811318f0cf078b78bfc
Es poden definir diferents providers per a diferents realms.
Resources
Qualsevol pàgina web podrà classificar les (sub)pàgines web per les que està formades en dos tipus:
Cal tenir en compte que Laravel com la majoria de Frameworks implementa el patró de disseny Front controller, és a dir, totes les URLs de la nostra aplicació es fan passar per un fitxer principal (index.php) que fa de controlador principal. El controlador principal utilitza un sistema bast en rutes per mapejar les diferents URLs de la nostra aplicació cap al codi/controladors dedicats per a cada URL.
El sistema ideal per complir amb SRP i no barrejar el codi d'autenticació amb altres codis és utilitzar un Middleware. Al fitxer app/Http/Kernel.php trobem el Kernel web (recordeu que també existeix el Kernel Console utilitzat per a utilitzar Laravel des de la línia de comandes amb php artisan). Al kernel web trobem predefinits els middlewares per a rutes:
https://github.com/laravel/laravel/blob/master/app/Http/Kernel.php
protected $routeMiddleware = [ 'auth' => \Illuminate\Auth\Middleware\Authenticate::class, 'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class, ... 'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class, .... ];
Bàsicament com podeu veure podem protegir rutes utilitzar el middleware auth que només permetrà l'accés a la ruta si s'està autenticat. També tenim el middleware guest que només permet accedir a una ruta si NO s'està autenticat!
https://github.com/illuminate/auth/blob/master/Middleware/Authenticate.php https://github.com/laravel/laravel/blob/master/app/Http/Middleware/RedirectIfAuthenticated.php
Si observeu els dos codis la responsabilitat de comprovar si un usuari està logat o no es delega en els Guards
A Laravel són els encarregats de comprovar l'autenticació o no d'un usuari. Vegem la interfície que ha de complir qualsevol Guard de Laravel:
https://laravel.com/api/5.3/Illuminate/Contracts/Auth/Guard.html https://github.com/illuminate/contracts/blob/master/Auth/Guard.php
interface Guard { /** * Determine if the current user is authenticated. * * @return bool */ public function check(); /** * Determine if the current user is a guest. * * @return bool */ public function guest(); /** * Get the currently authenticated user. * * @return \Illuminate\Contracts\Auth\Authenticatable|null */ public function user(); /** * Get the ID for the currently authenticated user. * * @return int|null */ public function id(); /** * Validate a user's credentials. * * @param array $credentials * @return bool */ public function validate(array $credentials = []); /** * Set the current user. * * @param \Illuminate\Contracts\Auth\Authenticatable $user * @return void */ public function setUser(Authenticatable $user); }
Els mètodes són:
On s'utilitzen?
És el guard utilitzat per defecte segons el fitxer config/auth.php. Correcte però quan es carrega aquest Guard a Laravel? Doncs on es carreguen tots els objectes durant l'arrancada d'una app Laravel utilitzant els Service Providers del fitxer config/app.php. Observareu dos que poden semblar relacionats amb l'Autenticació:
Illuminate\Auth\AuthServiceProvider::class App\Providers\AuthServiceProvider::clas --> NO
IMPORTANT: AuthServiceProvider fa referència a Authorization i no pas a Aunthentication
Per tant el que ens interessa és:
Illuminate\Auth\AuthServiceProvider [3]
Com podeu veure s'utilitza AuthManager/Illuminate\Auth\AuthManager per gestionar els Guards i els User Providers. Aquesta classe retorna el Guard que pertoqui segons la configuració del fitxer config/auth.php
AuthManager és registra al contenidor com auth AuthManager->guard() retorna el guard que estarà disponible al contenidor com auth.driver
AuthManager té el codi per als dos tipus de Guards disponibles de sèrie:
Tots els mètodes que no estiguin a Manager s'executen al default Guard:
public function __call($method, $parameters) { return $this->guard()->{$method}(...$parameters); }