41

Laravel 4 Cookbook (IT) - samples.leanpub.comsamples.leanpub.com/laravel4cookbook-it-sample.pdf · laravel-4-authentication ConfigurareilDatabase Uno dei modi migliori per gestire

  • Upload
    lekhanh

  • View
    228

  • Download
    0

Embed Size (px)

Citation preview

Laravel 4 Cookbook (IT)

Christopher Pitt, Taylor Otwell and Ionut Tanasa

This book is for sale at http://leanpub.com/laravel4cookbook-it

This version was published on 2015-03-27

This is a Leanpub book. Leanpub empowers authors and publishers with the Lean Publishingprocess. Lean Publishing is the act of publishing an in-progress ebook using lightweight tools andmany iterations to get reader feedback, pivot until you have the right book and build traction onceyou do.

©2013 - 2015 Christopher Pitt

Tweet This Book!Please help Christopher Pitt, Taylor Otwell and Ionut Tanasa by spreading the word about thisbook on Twitter!

The suggested tweet for this book is:

Ho appena comprato Laravel 4 Cookbook in Italiano.

The suggested hashtag for this book is #laravel4cookbook.

Find out what other people are saying about the book by clicking on this link to search for thishashtag on Twitter:

https://twitter.com/search?q=#laravel4cookbook

Indice

Installare Laravel 4 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1

Autenticazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Configurare il Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2

Connettersi al Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2Driver del Database . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3Il Driver Eloquent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Creare una Migration . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4Creare un Modello . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7Creare un Seminatore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

Configurare l’autenticazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10Autenticazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11

Creare il Layout per le Viste . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11Creare una Vista per il Login . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15Creare un’Azione per il Login . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16Autenticazione Utenti . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18Reindirizzamento con Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21Credenziali di Autenticazione . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23

Reimpostare le Password . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25Creare la Vista per Reimpostare la Password . . . . . . . . . . . . . . . . . . . . . . . 25Creare l’Azione di Reimpostazione della Password . . . . . . . . . . . . . . . . . . . 27

Lavorare con gli utenti autenticati . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33Creazione di una pagina profilo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33Creare i Filtri . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34Creare un’Azione per il Logout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

Installare Laravel 4Laravel 4 utilizza Composer per gestire le sue dipendenze. Potete installare Composer seguendo leistruzioni sul sito http://getcomposer.org/doc/00-intro.md#installation-nix.

Una volta installato, create una nuova cartella, o navigate in una già esistente, ed installatelo con ilseguente comando:

1 composer create-project laravel/laravel ./ --prefer-dist

Se scegliete di non installare Composer globalmente (anche se dovreste farlo), allora il comandodiventa:

1 php composer.phar create-project laravel/laravel ./ --prefer-dist

Entrambi i comandi inizieranno il processo di installazione di Laravel 4. Verranno scaricate tantedipendenze, quindi questo processo potrebbe richiedere un po’ di tempo.

AutenticazioneSe mi assomigliate almeno un po’; avrete passato un sacco di tempo a costruire sistemi protetti dapassword. Temevo sempre il momento in cui dovevo implementare il sistema di autenticazione diun CMS oppure di un carrello della spesa. Questo fino a quando non ho imparato quanto sia facilecon Laravel 4.

..

Il codice sorgente di questo capitolo è disponibile all’indirizzo:https://github.com/formativ/tutorial-laravel-4-authentication

Configurare il Database

Uno dei modi migliori per gestire gli utenti e l’autenticazione è salvarli in un database. Didefault i meccanismi di autenticazione di Laravel 4 presuppongono l’utilizzo di qualche forma diarchiviazione permanente, e fornisce due driver con i quali gli utenti presenti nel database possonoessere recuperati e autenticati.

Connettersi al Database

Per utilizzare uno dei driver forniti, prima dobbiamo creare una connessione valida al database.Impostatela configurando una delle sezioni nel file app/config/database.php. Ecco un esempio diun database MySQL che uso per testare:

1 <?php

2

3 return [

4 "fetch" => PDO::FETCH_CLASS,

5 "default" => "mysql",

6 "connections" => [

7 "mysql" => [

8 "driver" => "mysql",

9 "host" => "localhost",

10 "database" => "tutorial",

11 "username" => "dev",

12 "password" => "dev",

Autenticazione 3

13 "charset" => "utf8",

14 "collation" => "utf8_unicode_ci",

15 "prefix" => ""

16 ]

17 ],

18 "migrations" => "migration"

19 ];

..

Questo file deve essere salvato come app/config/database.php.

..

Ho eliminato i commenti, le linee estranee and configurazioni superflue dei driver.

Driver del Database

Il primo driver che Laravel 4 fornisce è chiamato database. Come suggerisce il nome; questo driverinterroga il database direttamente, per determinare se le credenziali fornite dall’utente esistono, e sele credenziali di autenticazione sono state fornite.

Se è questo il driver che volete usare, avrete bisogno della seguente tabella nel database che avetegià configurato:

1 CREATE TABLE `user` (

2 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

3 `username` varchar(255) DEFAULT NULL,

4 `password` varchar(255) DEFAULT NULL,

5 `email` varchar(255) DEFAULT NULL,

6 `created_at` datetime DEFAULT NULL,

7 `updated_at` datetime DEFAULT NULL,

8 PRIMARY KEY (`id`)

9 ) CHARSET=utf8 COLLATE=utf8_unicode_ci;

..

Qui, e successivamente, devierò dalla norma standard di utilizzare i nomi delle tabelle al plurale.Di solito, suggerirei di attenersi allo standard, però questo mi ha dato l’opportunità di dimostrarecome potresti configurare i nomi delle tabelle sia nelle migrazioni che nei modelli.

Autenticazione 4

..

Il Driver Eloquent

Il secondo driver the Laravel 4 fornisce è chiamato eloquent. Eloquent è il nome dell’ORM che vienefornito anche da Laravel 4, per l’astrazione dei dati del modello. E’ simile nel fatto che interrogheràuna base di dati per determinare se un utente è autentico, ma l’interfaccia che usa per determinarequesta cosa è un po’ diversa dalle interrogazioni dirette al database.

Se stai costruendo applicazioni medio-grandi, utlizzando Laravel 4, allora avrai una buona pos-sibilità di usare modelli Eloquent per rappresentare gli oggetti del database. E’ con questo inmente che spenderò del tempo elaborando il coinvolgimento dei modelli Eloquent nel processo diautenticazione.

..

Se preferisci ignorare tutte queste cose su Eloquent; sentiti livero di saltare le successive sezioniche parlano di migrazioni e modelli.

Creare una Migration

Siccome stiamo usanto Eloquent per gestire la communicazione tra la nostra applicazione e ildatabase; possiamo anche utilizare gli strumenti di manipolazione delle tabelle di Laravel 4.

Per iniziare, vai alla radice del tuo progetto e digita il seguente comando:

1 php artisan migrate:make --table="user" CreateUserTable

..

Il parametro –table=”user” combacia con l’attributo $table=user che defineremo nel modelloUser.

Questo genererà l’impalcatura per la tabella utenti, che dovrebbe somigliare a:

Autenticazione 5

1 <?php

2

3 use Illuminate\Database\Schema\Blueprint;

4 use Illuminate\Database\Migrations\Migration;

5

6 class CreateUserTable

7 extends Migration

8 {

9 public function up()

10 {

11 Schema::table('user', function(Blueprint $table)

12 {

13 //

14 });

15 }

16 public function down()

17 {

18 Schema::table('user', function(Blueprint $table)

19 {

20 //

21 });

22 }

23 }

..

Questo file deve essere salvato come app/database/migrations/0000_00_00_000000_CreateU-serTable.php. Il tuo potrebbe essere leggermente diverso in quanto gli 0 sono sostituiti da altrinumeri.

Lo schema di denominazione del file può sembrare strano, ma è così per una buona ragione. I sistemidi migrazione sono progettati per girare su qualsiasi server, e l’ordine in cui girano è preimpostato.Tutto ciò è per permettere alle modifiche del database di essere versionate.

La migrazione è creata con lo scheletro di base, ciò vuol dire che dobbiamo aggiungere noi i campialla tabella degli utenti:

Autenticazione 6

1 <?php

2

3 use Illuminate\Database\Schema\Blueprint;

4 use Illuminate\Database\Migrations\Migration;

5

6 class CreateUserTable

7 extends Migration

8 {

9 public function up()

10 {

11 Schema::create("user", function(Blueprint $table)

12 {

13 $table->increments("id");

14

15 $table

16 ->string("username")

17 ->nullable()

18 ->default(null);

19

20 $table

21 ->string("password")

22 ->nullable()

23 ->default(null);

24

25 $table

26 ->string("email")

27 ->nullable()

28 ->default(null);

29

30 $table

31 ->dateTime("created_at")

32 ->nullable()

33 ->default(null);

34

35 $table

36 ->dateTime("updated_at")

37 ->nullable()

38 ->default(null);

39 });

40 }

41

42 public function down()

Autenticazione 7

43 {

44 Schema::dropIfExists("user");

45 }

46 }

..

Questo file deve essere salvato come app/database/migrations/0000_00_00_000000_CreateUser-Table.php. Il vostro potrebbe essere leggermente diverso in quanto gli 0 sono sostituiti da altrinumeri.

Qui abbiamo aggiunto i campi per l’id, l’username, la password, la data di creazione e la data diaggiornamento. Ci sono dei metodi per abbreviare i campi timestamp, ma preferisco aggiungerliesplicitamente. Tutti i campi sono annullabili e il loro valore predefinito è null.

Abbiamo aggiunto anche il metodo drop, che verrà eseguito se le migrazioni sono invertite; cosa cheeliminerà la tabella utenti se esiste.

..

La scorciatoia per aggiungere i campi timestamps è disponibile all’indirizzo :http://laravel.com/docs/schema#adding-columns.

La migrazione funzionerà, anche se vorrai usare solo il driver database, ma è di solito parte di unaconfigurazione più grande; che include modelli e seeder.

Creare un Modello

Laravel 4 fornisce un modello User, con tutti i metodi che necessita. L’ho modificato leggermente,però l’essenziale è ancora lì…

1 <?php

2

3 use Illuminate\Auth\UserInterface;

4 use Illuminate\Auth\Reminders\RemindableInterface;

5

6 class User

7 extends Eloquent

8 implements UserInterface, RemindableInterface

9 {

10 protected $table = "user";

11 protected $hidden = ["password"];

Autenticazione 8

12

13 public function getAuthIdentifier()

14 {

15 return $this->getKey();

16 }

17

18 public function getAuthPassword()

19 {

20 return $this->password;

21 }

22

23 public function getReminderEmail()

24 {

25 return $this->email;

26 }

27 }

..

Questo file deve essere salvato come app/models/User.php.

..

Notare l’attributo $table=user che abbiamo definito. Deve corrispondere alla tabella che haidefinito nelle tue migrazioni.

Il modello User eredita Eloquent ed implementa due interfacce che assicurano che il modello siavalido per l’autenticazione. Parleremo di interfacce più tardi, ma è più importante notare i metodiche queste interfacce richiedono.

Laravel 4 permette la verifica dell’utente tramite un’indirizzo email od un nome utente, ma è uncampo diverso da quello che il ** getAuthIdentifier () ** ritorna.

Il metodo getReminderEmail() ritorna un’indirizzo email al quale contattare l’utente con una mailper resettare la password, qualora fosse necessario.

Altrimenti sei libero di personalizzare il modello, senza paura che si rompano i meccanismi diautenticazione integrati.

Creare un Seminatore

Laravel 4 include anche un sistema per popolare le tabelle, che può essere usato per aggiungere delletuple al tuo database dopo la migrazione iniziale. Per aggiungere un utente iniziale al mio progetto,

Autenticazione 9

ho la seguente classe seeder:

1 <?php

2

3 class UserSeeder

4 extends DatabaseSeeder

5 {

6 public function run()

7 {

8 $users = [

9 [

10 "username" => "christopher.pitt",

11 "password" => Hash::make("7h3¡MOST!53cu23"),

12 "email" => "[email protected]"

13 ]

14 ];

15

16 foreach ($users as $user)

17 {

18 User::create($user);

19 }

20 }

21 }

..

Questo file deve essere salvato come app/database/seeds/UserSeeder.php.

Eseguendola questa aggiungerà il mio account utente nel database, però per poterla eseguire;dobbiamo aggiungerla alla classe principale DatabaseSeeder:

1 <?php

2

3 class DatabaseSeeder

4 extends Seeder

5 {

6 public function run()

7 {

8 Eloquent::unguard();

9 $this->call("UserSeeder");

10 }

11 }

Autenticazione 10

..

Questo file deve essere salvato come app/database/seeds/DatabaseSeeder.php.

Adesso, quando la classe DatabaseSeeder viene richiamata; inserirà il mio account nella tabelladegli utenti. Se hai già impostato la vostra migrazione e il modello, e fornito dettagli validi per laconnessione al database, allora i seguenti comandi dovrebbero rendere tutto funzionante.

1 composer dump-autoload

2 php artisan migrate

3 php artisan db:seed

Il primo comando si assicura che le nuove classi che abbiamo creato vengono auto-caricatecorrettamente. Il secondo crea le tabelle nel database specificate dalle migrazioni. Il terzo inserisce idati dell’utente nella tabella degli utenti.

Configurare l’autenticazione

Le opzioni della configurazione per l’autenticazione sono sparse, però consentono qualche persona-lizzazione.

1 <?php

2

3 return [

4 "driver" => "eloquent",

5 "model" => "User",

6 "reminder" => [

7 "email" => "email.request",

8 "table" => "token",

9 "expire" => 60

10 ]

11 ];

..

Questo file deve essere salvato come app/config/auth.php.

Tutte queste impostazioni sono importanti, e la maggior parte si spiegano da sole. La vista usata percomporre le mail di richiesta è specificata da email ⇒ email.request e la durata di tempo dopo laquale il token per il reset scadrà è specificato da expire⇒ 60.

Autenticazione 11

..

Prestate attenzione alla vista specificata da email ⇒ email.request — dice a Laravel di caricareil file app/views/email/request.blade.php al posto del file di default app/views/emails/auth/re-minder.blade.php.

..

Ci sono varie cose che potrebbero trarre beneficio dalle opzioni di configurazione; le qualiattualmente sono inserite a mano nei provider. Ne guarderemo alcuni, quanto ci si presenteranno.

Autenticazione

Per consentire agli utenti di utilizzare la nostra applicazione, andremo a costruire una pagina per illogin; dove gli utenti potranno inserire le loro credenziali. Se le credenziali saranno valide, verrannoreindirizzati al loro profilo.

Creare il Layout per le Viste

Prima di creare qualunque pagina per la tua applicazione; sarebbe saggio astrarre tutto nel tuo layout.A questo fine; creeremo un layout con varie cose incluse, usando il template engine Blade.

Inanzitutto, dobbiamo creare il layout:

1 <!DOCTYPE html>

2 <html lang=”en”>

3 <head>

4 <meta charset="UTF-8" />

5 <link

6 type="text/css"

7 rel="stylesheet"

8 href="/css/layout.css" />

9 <title>

10 Tutorial

11 </title>

12 </head>

13 <body>

14 @include("header")

15 <div class="content">

16 <div class="container">

Autenticazione 12

17 @yield("content")

18 </div>

19 </div>

20 @include("footer")

21 </body>

22 </html>

..

Questo file deve essere salvato come app/views/layout.blade.php.

Il layout è per lo più composto daHTML, con due tag specifici di Blade dentro. I tag @include()dicono a Laravel di includere le viste (nominate con le stringhe; come header e footer) dalla cartellaviews.

Nota come abbiamo omesso l’estensione .blade.php? Laravel la aggiunge automaticamente per noi.Questa cosa vincola, inoltre, i dati forniti per la visualizzazione del layout a entrambi gli include.

Il secondo tag di Blade è @yield(). Questo tag accetta un nome di una sezione, è stampa a video idati di quella sezione. Queste viste nella tua applicazione estenderanndo questo layout; specificandole loro sezioni content (contenuto) così che il loro codice sia integrato nel codice del layout. Vedraia breve esattamente come si definiscono le sezioni.

1 @section("header")

2 <div class="header">

3 <div class="container">

4 <h1>Tutorial</h1>

5 </div>

6 </div>

7 @show

..

Questo file deve essere salvato come app/views/header.blade.php.

L’intestazione (header) contiene due tag Blade che, insieme, dicono a Blade dimemorizzare il markupnella sezione denominata, e presentarlo nel template.

Autenticazione 13

1 @section("footer")

2 <div class="footer">

3 <div class="container">

4 Powered by <a href="http://laravel.com/">Laravel</a>

5 </div>

6 </div>

7 @show

..

Questo file deve essere salvato come app/views/footer.blade.php.

Allo stessomodo, il piè di pagina (footer) avvolge il suomarkup in una sezione nominata e lo presentaal template immediatamente.

Ti starai chiedendo perchè abbiamo bisogno di integrare il markup, in questi file, nelle sezioni. Listiamo mostrando subito, dopo tutto. Facendo così ci permette di modificare il loro contenuto. Lovedremo presto in azione.

1 body

2 {

3 margin : 0;

4 padding : 0 0 50px 0;

5 font-family : "Helvetica", "Arial";

6 font-size : 14px;

7 line-height : 18px;

8 cursor : default;

9 }

10 a

11 {

12 color : #ef7c61;

13 }

14 .container

15 {

16 width : 960px;

17 position : relative;

18 margin : 0 auto;

19 }

20 .header, .footer

21 {

22 background : #000;

23 line-height : 50px;

Autenticazione 14

24 height : 50px;

25 width : 100%;

26 color : #fff;

27 }

28 .header h1, .header a

29 {

30 display : inline-block;

31 }

32 .header h1

33 {

34 margin : 0;

35 font-weight : normal;

36 }

37 .footer

38 {

39 position : absolute;

40 bottom : 0;

41 }

42 .content

43 {

44 padding : 25px 0;

45 }

46 label, input, .error

47 {

48 clear : both;

49 float : left;

50 margin : 5px 0;

51 }

52 .error

53 {

54 color : #ef7c61;

55 }

..

Questo file deve essere salvato come public/css/layout.css.

Finiamo con l’aggiunta di alcuni stili di base; che abbiamo collegato nell’elemento head. Questealtereranno i font di default e l’impaginazione. L’applicazione continuerebbe a funzionare, ma potràsembrare un po’ disordinata.

Autenticazione 15

Creare una Vista per il Login

La vista per il login è essenzialmente un modulo; nel quale gli utenti inseriscono le loro credenziali.

1 @extends("layout")

2 @section("content")

3 {{ Form::open([

4 "route" => "user/login",

5 "autocomplete" => "off"

6 ]) }}

7 {{ Form::label("username", "Username") }}

8 {{ Form::text("username", Input::old("username"), [

9 "placeholder" => "john.smith"

10 ]) }}

11 {{ Form::label("password", "Password") }}

12 {{ Form::password("password", [

13 "placeholder" => "����������"

14 ]) }}

15 {{ Form::submit("login") }}

16 {{ Form::close() }}

17 @stop

18 @section("footer")

19 @parent

20 <script src="//polyfill.io"></script>

21 @stop

..

Questo file deve essere salvato come app/views/user/login.blade.php.

Il primo tag Blade, nella vista di login, dice a Laravel che questa vista estende un layout. Il secondogli dice che markup includere nella sezione del contenuto. Questi tag formeranno le basi di tutte leviste (oltre alla impaginazione) che andremo a creare.

Usiamo successivamente {{ e }} per dire a Laravel che il codice contenuto deve essere interpretatocome PHP. Apriamo il modulo con il metodo Form::open(); fornendo un percorso al form per inviarei dati, e parametri facoltativi nel secondo argomento.

Poi definiamo due etichette e tre input. Le etichette accentano un parametro nome, seguito da unparametro testo. L’inserimento accetta il parametro nome and altri parametri opzionali. Infine, ilpulsante accetta un parametro nome e un parametro testo (simile alle etichette).

Chiudiamo il form con una chiamata a Form::close().

Autenticazione 16

..

Upi trovare maggiori informazioni sui metodi Form che Laravel offre al seguente indirizzo:http://laravel.com/docs/html.

L’ultima parte della vista di login è dove andiamo a sovrascrivere il markup di default del piédi pagina (specificato nel include del footer che abbiamo creato). Usiamo lo stesso nome per lasezione, ma non chiudiamo la sezione con @show. Si presenterà di già grazie a come abbiamodefinito l’include, quindo usiamo solo @stop nello stesso modo in cui abbiamo chiuso la sezionedel contenuto.

Usiamo, inoltre, il tag @parent per dire a Laravel che vogliamo stampare a video il markup cheabbiamo definito nel pié di pagina di default. Non lo cambiamo completamente, aggiungiamo solouno script.

..

Puoi scoprire di più sui tag Blade al seguente indirizzo: http://laravel.com/docs/templates#blade-templating

Lo script che abbiamo incluso è chiamato polyfill.io. E’ una collezione elementi per i browser chepermettono cose come l’attributo placeholder (che non sono sempre presenti nei browser menorecenti).

..

Puoi scoprire di più su Polyfill.io al seguente indirizzo:https://github.com/jonathantneal/polyfill

La nostra vista per il login è completata, ma praticamente inutile senza un codice sul lato server peraccettare l’inserimento e ritornare un risultato. Sistemiamo questa cosa!

Creare un’Azione per il Login

L’azione per il login è ciò che lega la logica dell’autenticazione alle viste che abbiamo creato. Seavete seguito innanzi, forse vi sarete chiesti quando proveremo tutto ciò nel browser. Fino a questopunto; non c’era niente che dicesso alla nostra applicazione di caricare tale vista.

Per iniziare; dobbiamo aggiungere un percorso per l’azione di login.

Autenticazione 17

1 <?php

2

3 Route::any("/", [

4 "as" => "user/login",

5 "uses" => "UserController@loginAction"

6 ]);

..

Questo file deve essere salvato come app/routes.php.

Il file “routes” mostra una pagina iniziale per una nuova applicazione Laravel 4, presentando unavista direttamente. Noi dobbiamo cambiarla in modo che utilizzi un’azione del controller. Non è chedobbiamo farlo per forza — potremmo altrettanto facilmente eseguire la logica nel file routes — manon sarebbe tanto ordinato.

Specifichiamo il nome per il percorso con as ⇒ user/login e gli diamo una destinazione con uses⇒ UserController@loginAction. Questo corrisponderà a tutte le chiamate al percorso di default/, e ha anche un nome che possiamo utilizzare per fare riferimento facilmente a questo percorso.

Successivamente, abbiamo bisogno di creare il controller.

1 <?php

2

3 class UserController

4 extends Controller

5 {

6 public function loginAction()

7 {

8 return View::make("user/login");

9 }

10 }

..

Questo file deve essere salvato come app/controllers/UserController.php.

Definiamo UserController (che estende la classe Controller). All’interno; abbiamo solo il metodologinAction() che abbiamo specificato nel file routes. Tutto ciò che fa questo metodo è presentarela vista di login al browser, però non è sufficiente per noi per essere in grado di vedere il nostroprogresso!

Autenticazione 18

Autenticazione Utenti

Giusto, quindi abbiamo il modulo e adesso abbiamo bisogno di legarlo al database in modo daautenticare gli utenti correttamente.

1 <?php

2

3 class UserController

4 extends Controller

5 {

6 public function loginAction()

7 {

8 if (Input::server("REQUEST_METHOD") == "POST")

9 {

10 $validator = Validator::make(Input::all(), [

11 "username" => "required",

12 "password" => "required"

13 ]);

14

15 if ($validator->passes())

16 {

17 echo "Validation passed!";

18 }

19 else

20 {

21 echo "Validation failed!";

22 }

23 }

24

25 return View::make("user/login");

26 }

27 }

..

Questo file deve essere salvato come app/controllers/UserController.php.

La nostra classe UserController è cambiata in qualche modo. In primo luogo, dobbiamo agiresui dati che vengono inviati al metodo loginAction(); e per fare ciò verifichiamo la proprietàREQUEST_METHOD del server. Se questo valore è POST allora possiamo presupporre che ilmodulo è stato inviato a questa azione, and procediamo con la fase di validazione.

Autenticazione 19

..

E’, inoltre, comune vedere azioni get e post separate per la stessa pagina. Anche se questo rende lecose un po ‘più ordinate, ed evita la necessità di verificare la proprietà REQUEST_METHOD, iopreferisco gestirle entrambe nella stessa azione.

Laravel 4 fornisce un ottimo sistema di validazione, e uno dei modi per utilizzarlo è chiamare ilmetodo Validator::make(). Il primo argomento è un array di dati da verificare, mentre il secondoargomento è un array di regole.

Abbiamo specificato che solo i campi nome utente e password siano necessari, ma ci sono tantealtre regole per la validazione (alcune delle quali useremo tra poco). La classe Validator ha inoltreun metodo passes(), che usiamo per dire se i dati inviati dal modulo sono validi.

..

Delle volte è meglio memorizzare la logica per la validazione fuori dal controller. Spesso io la mettoall’interno del modello, ma potreste creare anche una classe che gestisce e valida l’input.

Se inviate questo modulo; vi dirà se i campi richiesti sono stati forniti o no, ma c’è un modo piùelegante di mostrare questo tipo di messaggio…

1 <?php

2

3 use Illuminate\Support\MessageBag;

4

5 class UserController

6 extends Controller

7 {

8 public function loginAction()

9 {

10 $data = [];

11

12 if (Input::server("REQUEST_METHOD") == "POST")

13 {

14 $validator = Validator::make(Input::all(), [

15 "username" => "required",

16 "password" => "required"

17 ]);

18

19 if ($validator->passes())

20 {

Autenticazione 20

21 //

22 }

23 else

24 {

25 $data["errors"] = new MessageBag([

26 "password" => [

27 "Username and/or password invalid."

28 ]

29 ]);

30 }

31 }

32

33 return View::make("user/login", $data);

34 }

35 }

..

Questo file dovrebbe essere salvato come app/controllers/UserController.php.

Con i cambiamenti sopraindicati; andiamo a usare la classe MessageBag per salvare gli errori divalidazione. Questo è simile al modo in cui la classe di validazione salva implicitamente i proprierror, ma invece di mostrare singoli messaggi di errore sia per il nome utente che per la password;mostriamo un singolo messaggio di errore per entrambi. I moduli per il login sono un pochino piùsicuri in questo modo.

Per mostrare questo messaggio di errore, dobbiamo cambiare anche la vista per il login.

1 @extends("layout")

2 @section("content")

3 {{ Form::open([

4 "route" => "user/login",

5 "autocomplete" => "off"

6 ]) }}

7 {{ Form::label("username", "Username") }}

8 {{ Form::text("username", Input::get("username"), [

9 "placeholder" => "john.smith"

10 ]) }}

11 {{ Form::label("password", "Password") }}

12 {{ Form::password("password", [

13 "placeholder" => "••••••••••"

14 ]) }}

Autenticazione 21

15 @if ($error = $errors->first("password"))

16 <div class="error">

17 {{ $error }}

18 </div>

19 @endif

20 {{ Form::submit("login") }}

21 {{ Form::close() }}

22 @stop

23 @section("footer")

24 @parent

25 <script src="//polyfill.io"></script>

26 @stop

..

Questo file deve essere salvato come app/views/user/login.blade.php.

Come probabilmente puoi vedere; abbiamo aggiunto un controllo per verificare l’esistenza delmessaggio d’errore, e presentato dentro un elemento div. Se la validazione fallisce, vedrai adessoil messaggio d’errore sotto il campo della password.

Reindirizzamento con Input

Uno degli errori più comuni dei moduli è, ricaricando la pagina, il rinvio del modulo. Possiamosuperare questo con della magia di Laravel. Salveremo i dati inviati dal modulo nella sessione, ereindizzeremo alla pagina di login!

1 <?php

2

3 use Illuminate\Support\MessageBag;

4

5 class UserController

6 extends Controller

7 {

8 public function loginAction()

9 {

10 $errors = new MessageBag();

11

12 if ($old = Input::old("errors"))

13 {

14 $errors = $old;

Autenticazione 22

15 }

16

17 $data = [

18 "errors" => $errors

19 ];

20

21 if (Input::server("REQUEST_METHOD") == "POST")

22 {

23 $validator = Validator::make(Input::all(), [

24 "username" => "required",

25 "password" => "required"

26 ]);

27

28 if ($validator->passes())

29 {

30 //

31 }

32 else

33 {

34 $data["errors"] = new MessageBag([

35 "password" => [

36 "Username and/or password invalid."

37 ]

38 ]);

39

40 $data["username"] = Input::get("username");

41

42 return Redirect::route("user/login")

43 ->withInput($data);

44 }

45 }

46

47 return View::make("user/login", $data);

48 }

49 }

..

Questo file deve essere salvato come app/controllers/UserController.php.

La prima cosa che abbiamo fatta è stata di dichiarare una nuova istanza diMessageBag. Facciamoquesto perchè la vista continuerà a verrificare se ci sono errori MessageBag; anche se non è stato

Autenticazione 23

salvato nella sessione. Se lo è, invece, nella sessione; andiamo a sovrascrivere la nuova istanza cheabbiamo creato con l’istanza memorizzata.

La aggiungiamo poi all’array $data in modo da passarla alla vista e presentarla.

Se la validazione fallisce; memorizziamo il nome utente nell’array $data insieme agli errori divalidazione, e reindirizziamo allo stesso percorso (usando il metodowithInput() per memorizzare inostri dati nella sessione).

La nostra vista rimane la stessa, ma possiamo ricaricare la pagina senza l’orribile errore del modulo(ed i messaggi del browser fastidiosi che vanno con esso).

Credenziali di Autenticazione

L’ultimo passaggio nell’autenticazione è quello di confrontare i dati provenienti dal modulo con ildatabase. Laravel gestisce questo per noi con facilità.

1 <?php

2

3 use Illuminate\Support\MessageBag;

4

5 class UserController

6 extends Controller

7 {

8 public function loginAction()

9 {

10 $errors = new MessageBag();

11

12 if ($old = Input::old("errors"))

13 {

14 $errors = $old;

15 }

16

17 $data = [

18 "errors" => $errors

19 ];

20

21 if (Input::server("REQUEST_METHOD") == "POST")

22 {

23 $validator = Validator::make(Input::all(), [

24 "username" => "required",

25 "password" => "required"

26 ]);

27

Autenticazione 24

28 if ($validator->passes())

29 {

30 $credentials = [

31 "username" => Input::get("username"),

32 "password" => Input::get("password")

33 ];

34

35 if (Auth::attempt($credentials))

36 {

37 return Redirect::route("user/profile");

38 }

39 }

40

41 $data["errors"] = new MessageBag([

42 "password" => [

43 "Username and/or password invalid."

44 ]

45 ]);

46

47 $data["username"] = Input::get("username");

48

49 return Redirect::route("user/login")

50 ->withInput($data);

51 }

52

53 return View::make("user/login", $data);

54 }

55 }

..

Questo file deve essere salvato come app/controllers/UserController.php.

Dobbiamo semplicemente passare i dati inviati dal modulo ($credentials) al metodoAuth::atempt()e, se le credenziali sono valide, l’utente sarà autenticato e reindirizzato alla sua pagina profilo.

Abbiamo inoltre rimosso il codice degli errori fuori dalla clausola else. Così che funzionino inentrambi i casi sia per gli errori di validazione che per quelli di autenticazione. Lo stesso messaggiodi errore (nel caso delle pagine di login) va bene.

Autenticazione 25

Reimpostare le Password

Il meccanismo per la reimpostazione della password integrato in Laravel è ottimo! Andremo aimpostarlo in modo che gli utenti possano reimpostare le loro password fornendo solo il loroindirizzo email.

Creare la Vista per Reimpostare la Password

Abbiamo bisogno di due viste per permettere agli utenti di reimpostare le loro password. Abbiamobisogno di una vista dove possano inserire la loro email in modo da inviarli un codice direimpostazione, e una vista dove possano inserire la nuova password per il loro account.

1 @extends("layout")

2 @section("content")

3 {{ Form::open([

4 "route" => "user/request",

5 "autocomplete" => "off"

6 ]) }}

7 {{ Form::label("email", "Email") }}

8 {{ Form::text("email", Input::get("email"), [

9 "placeholder" => "[email protected]"

10 ]) }}

11 {{ Form::submit("reset") }}

12 {{ Form::close() }}

13 @stop

14 @section("footer")

15 @parent

16 <script src="//polyfill.io"></script>

17 @stop

..

Questo file deve essere salvato come app/views/user/request.blade.php.

Questa vista è simile a quella di login, solo che ha un solo campo per l’indirizzo email.

Autenticazione 26

1 @extends("layout")

2 @section("content")

3 {{ Form::open([

4 "url" => URL::route("user/reset") . $token,

5 "autocomplete" => "off"

6 ]) }}

7 @if ($error = $errors->first("token"))

8 <div class="error">

9 {{ $error }}

10 </div>

11 @endif

12 {{ Form::label("email", "Email") }}

13 {{ Form::text("email", Input::get("email"), [

14 "placeholder" => "[email protected]"

15 ]) }}

16 @if ($error = $errors->first("email"))

17 <div class="error">

18 {{ $error }}

19 </div>

20 @endif

21 {{ Form::label("password", "Password") }}

22 {{ Form::password("password", [

23 "placeholder" => "••••••••••"

24 ]) }}

25 @if ($error = $errors->first("password"))

26 <div class="error">

27 {{ $error }}

28 </div>

29 @endif

30 {{ Form::label("password_confirmation", "Confirm") }}

31 {{ Form::password("password_confirmation", [

32 "placeholder" => "••••••••••"

33 ]) }}

34 @if ($error = $errors->first("password_confirmation"))

35 <div class="error">

36 {{ $error }}

37 </div>

38 @endif

39 {{ Form::submit("reset") }}

40 {{ Form::close() }}

41 @stop

42 @section("footer")

Autenticazione 27

43 @parent

44 <script src="//polyfill.io"></script>

45 @stop

..

Questo file deve essere salvato come app/views/user/reset.blade.php.

Ok, finora avete capito. C’è un modulo con degli input e messaggi d’errore. Una cosa importanteda notare è il cambiamento dell’azione del modulo; cioè l’utilizzo di URL::route() insieme ad unavariabile assegnata alla vista. La imposteremo nell’azione, quindi non vi preoccupate di essa per ora.

Ho anche leggermente modificato la mail per la reimpostazione della password, anche se è per lopiù la stessa fornita da una installazione nuova di Laravel 4.

1 <!DOCTYPE html>

2 <html lang="en">

3 <head>

4 <meta charset="utf-8" />

5 </head>

6 <body>

7 <h1>Password Reset</h1>

8 To reset your password, complete this form:

9 {{ URL::route("user/reset") . "?token=" . $token }}

10 </body>

11 </html>

..

Questo file deve essere salvato come app/views/email/request.blade.php.

..

Ricordate che abbiamo cambiato la configurazione per spedire questa vista come predefinitaapp/views/emails/auth/reminder.blade.php.

Creare l’Azione di Reimpostazione della Password

Per far sì che le azioni siano accessibili; dobbiamo aggiungere percorsi per esse.

Autenticazione 28

1 <?php

2

3 Route::any("/", [

4 "as" => "user/login",

5 "uses" => "UserController@loginAction"

6 ]);

7

8 Route::any("/request", [

9 "as" => "user/request",

10 "uses" => "UserController@requestAction"

11 ]);

12

13 Route::any("/reset", [

14 "as" => "user/reset",

15 "uses" => "UserController@resetAction"

16 ]);

..

Questo file deve essere salvato come app/routes.php.

Ricordate; il percorso request è per richiedere il codice di reimpostazione, e il percorso reset è perreimpostare la password.

Abbiamo bisogno, anche, di generate la tabella dei codici di reimpostazione; usando artisan.

1 php artisan auth:reminders

Questo genererà un modello di migrazione per la tabella reminder.

1 <?php

2

3 use Illuminate\Database\Schema\Blueprint;

4 use Illuminate\Database\Migrations\Migration;

5

6 class CreateTokenTable

7 extends Migration

8 {

9 public function up()

10 {

11 Schema::create("token", function(Blueprint $table)

12 {

Autenticazione 29

13 $table

14 ->string("email")

15 ->nullable()

16 ->default(null);

17

18 $table

19 ->string("token")

20 ->nullable()

21 ->default(null);

22

23 $table

24 ->timestamp("created_at")

25 ->nullable()

26 ->default(null);

27 });

28 }

29

30 public function down()

31 {

32 Schema::dropIfExists("token");

33 }

34 }

..

Questo file deve essere salvato come app/database/migrations/0000_00_00_000000_CreateTo-kenTable.php. Il vostro potrebbe essere leggermente diverso in quanto gli 0 sono sostituiti da altrinumeri.

Ho modificato leggermente il modello, ma le basi sono le stesse. Questo creerà una tabella avente icampi email, token e created_at; che i meccanismi di autenticazione usano per generare e validarei codici di reimpostazione della password.

Con queste cose al loro posto, possiamo iniziare ad aggiungere le azioni per reimpostare la password.

Autenticazione 30

1 public function requestAction()

2 {

3 $data = [

4 "requested" => Input::old("requested")

5 ];

6

7 if (Input::server("REQUEST_METHOD") == "POST")

8 {

9 $validator = Validator::make(Input::all(), [

10 "email" => "required"

11 ]);

12

13 if ($validator->passes())

14 {

15 $credentials = [

16 "email" => Input::get("email")

17 ];

18

19 Password::remind($credentials,

20 function($message, $user)

21 {

22 $message->from("[email protected]");

23 }

24 );

25

26 $data["requested"] = true;

27

28 return Redirect::route("user/request")

29 ->withInput($data);

30 }

31 }

32

33 return View::make("user/request", $data);

34 }

..

Questo è stato estratto da app/controllers/UserController.php.

Il metodo requestAction() convalida i dati inviati dal modulo allo stesso modo del metodologinAction(), ma invece di passare i dati a Auth::atempt(), li passa a Password::remind(). Questo

Autenticazione 31

metodo accetta un array di credenziali (che di solito contiene un’indirizzo email), e anche unparametro opzionale con il quale si può personalizzare l’email che viene inviato.

1 public function resetAction()

2 {

3 $token = "?token=" . Input::get("token");

4

5 $errors = new MessageBag();

6

7 if ($old = Input::old("errors"))

8 {

9 $errors = $old;

10 }

11

12 $data = [

13 "token" => $token,

14 "errors" => $errors

15 ];

16

17 if (Input::server("REQUEST_METHOD") == "POST")

18 {

19 $validator = Validator::make(Input::all(), [

20 "email" => "required|email",

21 "password" => "required|min:6",

22 "password_confirmation" => "same:password",

23 "token" => "exists:token,token"

24 ]);

25

26 if ($validator->passes())

27 {

28 $credentials = [

29 "email" => Input::get("email")

30 ];

31

32 Password::reset($credentials,

33 function($user, $password)

34 {

35 $user->password = Hash::make($password);

36 $user->save();

37

38 Auth::login($user);

39 return Redirect::route("user/profile");

40 }

Autenticazione 32

41 );

42 }

43

44 $data["email"] = Input::get("email");

45

46 $data["errors"] = $validator->errors();

47

48 return Redirect::to(URL::route("user/reset") . $token)

49 ->withInput($data);

50 }

51

52 return View::make("user/reset", $data);

53 }

..

Questo è stato estratto da app/controllers/UserController.php.

Il metodo resetAction() è principalmente lo stesso. Iniziamo creando la stringa contenente il codicedi reimpostazione (che usiamo anche per il reindirizzamento, per mantenere il codice in tutti gli statidella pagina di reset). Andiamo a prendere i vecchi messaggi di errore, come abbiamo già fatto perla pagina di login, e validiamo i dati spediti dal modulo.

Se tutto i dati sono validi, li passiamo a Password::reset(). Il secondo parametro rappresenta la logicusata per aggiornare la tupla che corrisponde all’utente nel database. Aggiorniamo la password,salviamo la password nel database e automaticamente autentichiamo l’utente.

Se tutto è andato secondi i piani; reindirizziamo alla pagina profilo. Altrimenti; reindirizziamo allapagina di reset, passandole i messaggi d’errore.

..

C’è una strana cosa sul meccanismo di autenticazione qui; i campi password/token sono scritti amano e la validazione è integrata nella funzionePassword::reset() che non usa la classeValidation.Quindi finchè i nomi dei campi sono password, password_confirmation e token, e la vostrapassword è più lunga di 6 caratteri, non dovreste notare questa cosa strana.

In alternativa, puoi modificare i nomi dei campi e la validazione applicata nel file vendor/larave-l/framework/src/Illuminate/Auth/Reminders/PasswordBroker.php o implementare il proprioReminderServiceProvider che sostituisca quello fornito da Laravel 4. I dettagli di queste duesoluzioni non seguono lo scopo di questa guida. Puoi trovare maggiori informazioni sulla creazionedi service providers nell’eccellente libro di Taylor Otwell, a: https://leanpub.com/laravel

Autenticazione 33

..

Come ho già specificato prima, puoi impostare la quantità di tempo dopo la quale i codici direimpostazione scadranno; nel file app/config/auth.php.

..

Puoi averemaggiori informazioni suimetodi di autenticazione, all’indirizzo:http://laravel.com/docs/security#authenticating-users

..

Puoi averemaggiori informazioni suimetodi per lemail, all’indirizzo:http://laravel.com/docs/mail

Lavorare con gli utenti autenticati

Ok. Abbiamo il login e la reimpostazione della password sotto la nostra cintura. La parte finale diquesto tutorial è di utilizzare i dati della sessione utente nella nostra applicazione, e di proteggerel’accesso non autenticato alle parti sicure della nostra applicazione.

Creazione di una pagina profilo

Per mostrare alcuni dei dati della sessione dove l’utente ha accesso, andiamo ad implementare lavista profilo.

1 @extends("layout")

2 @section("content")

3 <h2>Hello {{ Auth::user()->username }}</h2>

4 <p>Welcome to your sparse profile page.</p>

5 @stop

..

Questo file deve essere salvato come app/views/user/profile.blade.php.

Questa pagina profilo incredibilmente semplice sfoggia una singola cosa, è possibile ottenere i datidal modello utente accedendo all’oggetto restituito dal metodo ** Auth :: user () ** . Tutti i campiche avete definito su questo modello (o tabella del database) sono accessibili in questo modo.

Autenticazione 34

1 public function profileAction()

2 {

3 return View::make("user/profile");

4 }

..

Questo è stato estratto da app/controllers/UserController.php.

Il metodo profileAction() è altrettanto semplice come la vista. Non abbiamo bisogno di passare alcundato alla vista, o anche di impossessarci della sessione utente utilizzando qualche codice speciale.Auth::user() fa tutto!

Per rendere questa pagina accessibile, dobbiamo aggiungere un percorso per essa. Andremo a farlotra qualche istante; ma adesso è il momento di parlare di come proteggere le pagine sensibili dellanostra applicazione…

Creare i Filtri

Laravel 4 include un file di filtri, in cui possiamo definire filtri per singoli (o anche gruppi di) percorsi.

1 <?php

2

3 Route::filter("auth", function()

4 {

5 if (Auth::guest())

6 {

7 return Redirect::route("user/login");

8 }

9 });

10

11 Route::filter("guest", function()

12 {

13 if (Auth::check())

14 {

15 return Redirect::route("user/profile");

16 }

17 });

18

19 Route::filter("csrf", function()

20 {

21 if (Session::token() != Input::get("_token"))

Autenticazione 35

22 {

23 throw new Illuminate\Session\TokenMismatchException;

24 }

25 });

..

Questo file deve essere salvato come app/filters.php.

Il primo filtro è per i percorsi (o per le pagine se preferite) per i quali l’utente deve essere autenticato.Il secondo è per l’esatto incontrario; per il quale gli utenti non devono essere autenticati. L’ultimofiltro è quello che abbiamo usato finora.

Quando usiamo il metodo Form::open(); Laravel automaticamente aggiunte un campo nascosto ainostri moduli. Questo campo contiene un codice speciale di sicurezza che viene verificato ogni voltache il modulo viene inviato. Non avete davvero bisogno di capire perché questo è più sicuro …

..

…però se volete, leggete questo:http://blog.ircmaxell.com/2013/02/preventing-csrf-attacks.html

Per essere in grado di applicare questi filtri, dobbiamo modificare il nostro file dei percorsi.

1 <?php

2

3 Route::group(["before" => "guest"], function()

4 {

5 Route::any("/", [

6 "as" => "user/login",

7 "uses" => "UserController@loginAction"

8 ]);

9

10 Route::any("/request", [

11 "as" => "user/request",

12 "uses" => "UserController@requestAction"

13 ]);

14

15 Route::any("/reset", [

16 "as" => "user/reset",

17 "uses" => "UserController@resetAction"

18 ]);

Autenticazione 36

19 });

20

21 Route::group(["before" => "auth"], function()

22 {

23 Route::any("/profile", [

24 "as" => "user/profile",

25 "uses" => "UserController@profileAction"

26 ]);

27

28 Route::any("/logout", [

29 "as" => "user/logout",

30 "uses" => "UserController@logoutAction"

31 ]);

32 });

..

Questo file deve essere salvato come app/routes.php.

Per proteggere parti della nostra application, raggruppiamo i percorsi con il metodo Route::group().Il primo argomento ci permette di specificare quali filtri applicare ai percorsi racchiusi. Vogliamoraggruppare tutti i nostri percorsi per i quali l’utente non deve essere autenticato; per far sì che gliutenti non le vedano quando sono autenticati. Facciamo l’esatto opposto per la pagina di profiloperchè solo gli utenti autenticati dovrebbero essere in grado di vedere le proprie pagine profilo.

Creare un’Azione per il Logout

Per testare queste nuove misure di sicurezza (e per arrotondare il tutorial), abbiamo bisogno di creareil metodo logoutAction() e aggiungere gli indirizzi alla barra di navigazione in modo che gli utentipossano eseguire il logout.

1 public function logoutAction()

2 {

3 Auth::logout();

4 return Redirect::route("user/login");

5 }

..

Questo è stato estratto da app/controllers/UserController.php.

Autenticazione 37

Il metodo logoutAction() chiama il metodo Auth::logout() per chiudere la sessione utente, ereindirizza alla pagina di login. Un gioco da ragazzi!

Questo è ciò che la nuova intestazione assomiglia:

1 @section("header")

2 <div class="header">

3 <div class="container">

4 <h1>Tutorial</h1>

5 @if (Auth::check())

6 <a href="{{ URL::route("user/logout") }}">

7 logout

8 </a>

9 |

10 <a href="{{ URL::route("user/profile") }}">

11 profile

12 </a>

13 @else

14 <a href="{{ URL::route("user/login") }}">

15 login

16 </a>

17 @endif

18 </div>

19 </div>

20 @show

..

Questo file deve essere salvato come app/views/header.blade.php.