Italian (Italiano) translation by Francesco (you can also view the original English article)
Oggi andremo a discutere il sistema di autorizzazione del framework web Laravel. Il framework Laravel implementa l'autorizzazione sotto forma di gates e policies. Dopo un'introduzione a gates e policies, illustrerò i concetti implementando un esempio personalizzato.
Presumo che tu sia già conoscenza del sistema di autenticazione Laravel incorporato che è essenziale per comprendere il concetto di autorizzazione. Ovviamente, il sistema di autorizzazione funziona in combinazione con il sistema di autenticazione per identificare la sessione utente legittima.
Se non conoscete il sistema di autenticazione di Laravel, consiglio vivamente di guardare la documentazione ufficiale, che vi offre uno spaccato del soggetto.
Approccio di Laravel all'autorizzazione
A questo punto, si dovrebbe già sapere che il sistema di autorizzazione Laravel è implementato in due modi — gates e policies. Anche se può sembrare un affare complicato, direi che è abbastanza facile implementarlo una volta capito il succo!
I gates consentono di definire una regola di autorizzazione utilizzando un approccio basato su closures. In altre parole, quando si desidera autorizzare un'azione che non è correlata ad alcun modello specifico, il gate è il luogo ideale per implementare tale logica.
Diamo un rapido sguardo all'autorizzazione basata su gate:
... ... Gate::define('update-post', function ($user, $post) { return $user->id == $post->user_id; }); ... ...
Questo frammento di codice definisce la regola di autorizzazione update-post
che è possibile chiamare da qualsiasi punto dell'applicazione.
D'altra parte, è necessario utilizzare criteri quando si desidera raggruppare la logica di autorizzazione di qualsiasi modello. Ad esempio, supponiamo di avere un modello Post nell'applicazione e che desideriamo autorizzare le azioni CRUD su quel modello. In quel caso, è la policy che è necessario implementare.
class PostPolicy { public function view(User $user, Post $post) {} public function create(User $user) {} public function update(User $user, Post $post) {} public function delete(User $user, Post $post) {} }
Come potete vedere, è una classe abbastanza semplice che definisce l'autorizzazione per le operazioni CRUD del modello Post
.
Questa era un'introduzione ai gates e policies in Laravel. Nella sezione successiva andremo a vedere una dimostrazione pratica di ogni elemento.
Gates
In questa sezione, vedremo un esempio reale per comprendere il concetto di gates.
Di solito, si finisce per guardare al provider di servizi di Laravel quando è necessario registrare un componente o un servizio. Seguendo tale convenzione, andiamo avanti e definire il nostro gate personalizzato in app/Providers/AuthServiceProvider.php
come illustrato nel seguente frammento.
<?php namespace App\Providers; use Illuminate\Support\Facades\Gate; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Http\Request; class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); Gate::define('update-post', function ($user, $post) { return $user->id == $post->user_id; }); } }
Nel metodo di boot
, abbiamo definito il nostro gate personalizzato:
Gate::define('update-post', function ($user, $post) { return $user->id == $post->user_id; });
Durante la definizione di un gate, ci vuole una closure che restituisce TRUE o FALSE in base alla logica di autorizzazione che è definita nella definizione del gate. Oltre alla funzione di closure, ci sono altri modi in cui è possibile definire gates.
Ad esempio, la seguente definizione di gate chiama l'azione di un controller anziché la funzione di closure.
Gate::define('update-post', 'ControllerName@MethodName');
Ora, andiamo avanti e aggiungiamo una route personalizzata in modo che possiamo dimostrare come funziona l'autorizzazione basata su gate. Nel file routes/web.php
, aggiungiamo la seguente route.
Route::get('service/post/gate', 'PostController@gate');
Creiamo un controller associato nel file app/Http/Controllers/PostController.php
.
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Post; use Illuminate\Support\Facades\Gate; class PostController extends Controller { /* Make sure you don't user Gate and Policy altogether for the same Model/Resource */ public function gate() { $post = Post::find(1); if (Gate::allows('update-post', $post)) { echo 'Allowed'; } else { echo 'Not Allowed'; } exit; } }
Nella maggior parte dei casi, si finirà per utilizzare il metodo allows
o denies
del facade del Gate
per autorizzare una determinata azione. Nel nostro esempio precedente, abbiamo usato il metodo allows
per controllare se l'utente corrente è in grado di eseguire l'azione di update-post
.
Gli utenti più attenti avrebbero notato che abbiamo passato solo il secondo argomento $post
alla closure. Il primo argomento, l'utente loggato corrente, viene inserito automaticamente dal facade del Gate
.
Ecco come dovresti utilizzare i gates per autorizzare azioni nell'applicazione Laravel. La sezione successiva è tutto su come utilizzare le policies, se si desidera implementare l'autorizzazione per i vostri modelli.
Policies
Come abbiamo detto in precedenza, quando si desidera raggruppare logicamente le vostre azioni di autorizzazione per qualsiasi modello particolare o risorsa, bisogna usare le policies.
In questa sezione, creeremo una policy per il modello Post che verrà utilizzato per autorizzare tutte le azioni CRUD. Presumo che hai già implementato il modello Post nell'applicazione; in caso contrario, sarà qualcosa di simile.
Il comando artisan
Laravel è il tuo migliore amico quando si tratta di creare prototipi di codice. È possibile utilizzare il seguente comando artisan per creare un criterio per il modello Post.
$php artisan make:policy PostPolicy --model=Post
Come potete vedere, abbiamo inserito l'argomento --model=Post
, in modo da creare tutti i metodi CRUD. In mancanza di ciò, creerà una classe policy vuota. È possibile individuare la classe Policy appena creata nel percorso app/Policies/PostPolicy.php
.
Cerchiamo di sostituirlo con il codice riportato di seguito.
<?php namespace App\Policies; use App\User; use App\Post; use Illuminate\Auth\Access\HandlesAuthorization; class PostPolicy { use HandlesAuthorization; /** * Determine whether the user can view the post. * * @param \App\User $user * @param \App\Post $post * @return mixed */ public function view(User $user, Post $post) { return TRUE; } /** * Determine whether the user can create posts. * * @param \App\User $user * @return mixed */ public function create(User $user) { return $user->id > 0; } /** * Determine whether the user can update the post. * * @param \App\User $user * @param \App\Post $post * @return mixed */ public function update(User $user, Post $post) { return $user->id == $post->user_id; } /** * Determine whether the user can delete the post. * * @param \App\User $user * @param \App\Post $post * @return mixed */ public function delete(User $user, Post $post) { return $user->id == $post->user_id; } }
Per essere in grado di utilizzare la nostra classe Policy, abbiamo bisogno di registrarla utilizzando il provider di servizi Laravel come illustrato nel seguente frammento di codice.
<?php namespace App\Providers; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; use Illuminate\Http\Request; use App\Post; use App\Policies\PostPolicy; class AuthServiceProvider extends ServiceProvider { /** * The policy mappings for the application. * * @var array */ protected $policies = [ 'App\Model' => 'App\Policies\ModelPolicy', Post::class => PostPolicy::class ]; /** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); } }
Abbiamo aggiunto il mapping della nostra policy nella proprietà $policies
. Dice a Laravel di chiamare il metodo corrispondente della policy per autorizzare l'azione CRUD.
È inoltre necessario registrare le policies utilizzando il metodo registerPolicies
, come abbiamo fatto nel metodo di boot
.
Andando avanti, creiamo un paio di percorsi personalizzati nel file routes/web.php
in modo da poter testare i nostri metodi di policy.
Route::get('service/post/view', 'PostController@view'); Route::get('service/post/create', 'PostController@create'); Route::get('service/post/update', 'PostController@update'); Route::get('service/post/delete', 'PostController@delete');
Infine, creiamo un controller associato in app/Http/Controllers/PostController.php
.
<?php namespace App\Http\Controllers; use App\Http\Controllers\Controller; use App\Post; use Illuminate\Support\Facades\Auth; class PostController extends Controller { public function view() { // get current logged in user $user = Auth::user(); // load post $post = Post::find(1); if ($user->can('view', $post)) { echo "Current logged in user is allowed to update the Post: {$post->id}"; } else { echo 'Not Authorized.'; } } public function create() { // get current logged in user $user = Auth::user(); if ($user->can('create', Post::class)) { echo 'Current logged in user is allowed to create new posts.'; } else { echo 'Not Authorized'; } exit; } public function update() { // get current logged in user $user = Auth::user(); // load post $post = Post::find(1); if ($user->can('update', $post)) { echo "Current logged in user is allowed to update the Post: {$post->id}"; } else { echo 'Not Authorized.'; } } public function delete() { // get current logged in user $user = Auth::user(); // load post $post = Post::find(1); if ($user->can('delete', $post)) { echo "Current logged in user is allowed to delete the Post: {$post->id}"; } else { echo 'Not Authorized.'; } } }
Ci sono diversi modi in cui si potrebbero autorizzare le vostre azioni utilizzando le Policies. Nel nostro esempio precedente, abbiamo utilizzato il modello User
per autorizzare le azioni del nostro modello di Post
.
Il modello di User fornisce due metodi utili per scopi di autorizzazione — can
e cant
. Il metodo can
viene utilizzato per verificare se l'utente corrente è in grado di eseguire una determinata azione. E la controparte del metodo can
, il metodo cant
, viene utilizzata per determinare l'impossibilità di esecuzione dell'azione.
Prendiamo il frammento del metodo view
dal controller per vedere che cosa esattamente fa.
public function view() { // get current logged in user $user = Auth::user(); // load post $post = Post::find(1); if ($user->can('view', $post)) { echo "Current logged in user is allowed to update the Post: {$post->id}"; } else { echo 'Not Authorized.'; } }
In primo luogo, carichiamo l'utente attualmente loggato, che ci dà l'oggetto del modello User. Successivamente, carichiamo un post di esempio utilizzando il modello per i Post.
Andando avanti, abbiamo utilizzato il metodo can
del modello User per autorizzare l'azione di view
del modello Post
. Il primo argomento del metodo can
è il nome dell'azione che si desidera autorizzare, e il secondo argomento è l'oggetto del modello di cui si desidera ottenere l'autorizzazione.
Questa era una dimostrazione di come utilizzare il modello di User
per le azioni utilizzando le policies di autorizzazione. In alternativa, è possibile utilizzare il Controller Helper, se sei nel controller mentre si autorizza una certa azione.
… $this->authorize('view', $post); …
Come potete vedere, non è necessario caricare il modello di User se si utilizza il Controller Helper.
Questo era il concetto di policies a vostra disposizione, ed è molto utile mentre si autorizza un modello o una risorsa poichè ti permette di raggruppare la logica di autorizzazione in un unico punto.
Basta fare in modo che non si utilizzi gates e policies insieme per le stesse azioni del modello, altrimenti si avranno problemi. Questo è tutto da parte mia per oggi!
Conclusione
Oggi, è stato l'autorizzazione di Laravel che ha preso il centro della scena nel mio articolo. All'inizio dell'articolo, ho introdotto i principali elementi di autorizzazione di Laravel, gates e policies.
In seguito siamo andati attraverso la creazione di nostro gate personalizzato e policy personalizzata per vedere come funziona nel mondo reale. Spero che abbia apprezzato l'articolo e imparato qualcosa di utile nel contesto di Laravel.
Per quelli di voi che da poco hanno iniziato con Laravel o stanno cercando di espandere il sito o applicazione con estensioni, abbiamo una varietà di cose da studiare nel mercato di Envato.
Come sempre, mi piacerebbe sentire i vostri commenti usando il feed qui sotto!