Prologo
Primi Passi
Architettura
Le Basi
- Routing
- Middleware
- Protezione da CSRF
- Controller
- Richieste
- Risposte
- Views
- Blade
- Vite
- URL
- Sessioni
- Validazione
- Errori
- Logging
Approfondimenti
- Artisan
- Broadcasting
- Cache
- Collezioni
- Concorrenza
- Contesto
- Contratti
- Eventi
- File System
- Helpers
- Client HTTP
- Localizzazione
- Notifiche
- Sviluppo di Package
- Processi
- Code
- Rate-limiting
- Stringhe
- Scheduling di Task
Sicurezza
Database
Eloquent ORM
Testing
Package
Autorizzazione
- Introduzione
- Gates
- Creare Policy
- Scrivere Policies
- Autorizzare le Azioni con le Policy
- Autorizzazione & Inertia
Introduzione
Oltre a fornire servizi di autenticazione integrati, Laravel offre anche un modo semplice per autorizzare le azioni degli utenti su una determinata risorsa. Ad esempio, anche se un utente è autenticato, potrebbe non essere autorizzato ad aggiornare o eliminare alcuni modelli Eloquent o record del database gestiti dalla tua applicazione. Le funzionalità di autorizzazione di Laravel offrono un metodo facile e organizzato per gestire questi tipi di controlli di autorizzazione.
Laravel offre due principali modalità per autorizzare le azioni: gates e policies. Pensa a gates e policies come a routes e controllers. Le gates forniscono un approccio semplice basato su chiusure per l’autorizzazione, mentre le policies, come i controllers, raggruppano la logica attorno a un modello o risorsa specifica. In questa documentazione, esploreremo prima le gates e poi analizzeremo le policies.
Non è necessario scegliere tra l’uso esclusivo delle gates o delle policies quando costruisci un’applicazione. La maggior parte delle applicazioni avrà probabilmente una combinazione di gates e policies, ed è perfettamente normale! Le gates sono più adatte per azioni che non sono legate a nessun modello o risorsa, come visualizzare una dashboard amministrativa. Al contrario, le policies dovrebbero essere utilizzate quando desideri autorizzare un’azione per un particolare modello o risorsa.
Gates
Scrivere Gates
I Gates sono un ottimo modo per apprendere le basi delle funzionalità di autorizzazione di Laravel; tuttavia, quando costruisci applicazioni Laravel robuste, dovresti considerare l’uso delle policies per organizzare le tue regole di autorizzazione.
I Gates sono semplicemente closures che determinano se un utente è autorizzato a eseguire una determinata azione. Tipicamente, i gates sono definiti all’interno del metodo boot
della classe App\Providers\AppServiceProvider
utilizzando il facade Gate
. I gates ricevono sempre un’istanza di utente come primo argomento e possono opzionalmente ricevere ulteriori argomenti, come un modello Eloquent pertinente.
In questo esempio, definiamo un gate per determinare se un utente può aggiornare un determinato modello App\Models\Post
. Il gate realizza questo confrontando l’id
dell’utente con il user_id
dell’utente che ha creato il post:
use App\Models\Post;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Gate::define('update-post', function (User $user, Post $post) {
return $user->id === $post->user_id;
});
}
Come i controller, i gates possono essere definiti anche usando un array di callback di classe:
use App\Policies\PostPolicy;
use Illuminate\Support\Facades\Gate;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Gate::define('update-post', [PostPolicy::class, 'update']);
}
Autorizzare le Azioni
Per autorizzare un’azione utilizzando i gate, dovresti usare i metodi allows
o denies
forniti dalla facciata Gate
. Nota che non è necessario passare l’utente attualmente autenticato a questi metodi. Laravel si occuperà automaticamente di passare l’utente alla chiusura del gate. È comune chiamare i metodi di autorizzazione del gate all’interno dei controller della tua applicazione prima di eseguire un’azione che richiede autorizzazione:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller
{
/**
* Aggiorna il post dato.
*/
public function update(Request $request, Post $post): RedirectResponse
{
if (! Gate::allows('update-post', $post)) {
abort(403);
}
// Aggiorna il post...
return redirect('/posts');
}
}
Se desideri verificare se un utente diverso da quello attualmente autenticato è autorizzato a eseguire un’azione, puoi usare il metodo forUser
sulla facciata Gate
:
if (Gate::forUser($user)->allows('update-post', $post)) {
// L'utente può aggiornare il post...
}
if (Gate::forUser($user)->denies('update-post', $post)) {
// L'utente non può aggiornare il post...
}
Puoi autorizzare più azioni contemporaneamente utilizzando i metodi any
o none
:
if (Gate::any(['update-post', 'delete-post'], $post)) {
// L'utente può aggiornare o eliminare il post...
}
if (Gate::none(['update-post', 'delete-post'], $post)) {
// L'utente non può aggiornare o eliminare il post...
}
Autorizzare o Lanciare Eccezioni
Se vuoi provare ad autorizzare un’azione e automaticamente lanciare un Illuminate\Auth\Access\AuthorizationException
se l’utente non è autorizzato a eseguire l’azione richiesta, puoi usare il metodo authorize
della facciata Gate
. Le istanze di AuthorizationException
vengono automaticamente convertite in una risposta HTTP 403 da Laravel:
Gate::authorize('update-post', $post);
// L'azione è autorizzata...
Fornire Contesto Aggiuntivo
I metodi del gate per autorizzare le abilità (allows
, denies
, check
, any
, none
, authorize
, can
, cannot
) e le directive di autorizzazione Blade (@can
, @cannot
, @canany
) possono ricevere un array come secondo argomento. Gli elementi di questo array vengono passati come parametri alla chiusura del gate e possono essere utilizzati per fornire contesto aggiuntivo quando si prendono decisioni di autorizzazione:
use App\Models\Category;
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::define('create-post', function (User $user, Category $category, bool $pinned) {
if (! $user->canPublishToGroup($category->group)) {
return false;
} elseif ($pinned && ! $user->canPinPosts()) {
return false;
}
return true;
});
if (Gate::check('create-post', [$category, $pinned])) {
// L'utente può creare il post...
}
Risposte del Gate
Finora, abbiamo esaminato solo i gate che restituiscono semplici valori booleani. Tuttavia, a volte potresti voler restituire una risposta più dettagliata, inclusa un messaggio di errore. Per farlo, puoi restituire un Illuminate\Auth\Access\Response
dal tuo gate:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::deny('You must be an administrator.');
});
Anche quando restituisci una risposta di autorizzazione dal tuo gate, il metodo Gate::allows
restituirà comunque un semplice valore booleano; tuttavia, puoi utilizzare il metodo Gate::inspect
per ottenere la risposta completa di autorizzazione restituita dal gate:
$response = Gate::inspect('edit-settings');
if ($response->allowed()) {
// The action is authorized...
} else {
echo $response->message();
}
Quando usi il metodo Gate::authorize
, che genera un’AuthorizationException
se l’azione non è autorizzata, il messaggio di errore fornito dalla risposta di autorizzazione verrà propagato alla risposta HTTP:
Gate::authorize('edit-settings');
// The action is authorized...
Personalizzazione dello Stato della Risposta HTTP
Quando un’azione viene negata tramite una Gate, viene restituita una risposta HTTP 403
; tuttavia, a volte può essere utile restituire un codice di stato HTTP alternativo. Puoi personalizzare il codice di stato HTTP restituito per un controllo di autorizzazione fallito usando il costruttore statico denyWithStatus
della classe Illuminate\Auth\Access\Response
:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyWithStatus(404);
});
Poiché nascondere le risorse tramite una risposta 404
è uno schema molto comune per le applicazioni web, viene offerto il metodo denyAsNotFound
per comodità:
use App\Models\User;
use Illuminate\Auth\Access\Response;
use Illuminate\Support\Facades\Gate;
Gate::define('edit-settings', function (User $user) {
return $user->isAdmin
? Response::allow()
: Response::denyAsNotFound();
});
Intercettare i Controlli del Gate
A volte potresti voler concedere tutte le autorizzazioni a un utente specifico. Puoi usare il metodo before
per definire una closure che viene eseguita prima di tutti gli altri controlli di autorizzazione:
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::before(function (User $user, string $ability) {
if ($user->isAdministrator()) {
return true;
}
});
Se la closure before
restituisce un risultato non nullo, tale risultato sarà considerato come risultato del controllo di autorizzazione.
Puoi usare il metodo after
per definire una closure da eseguire dopo tutti gli altri controlli di autorizzazione:
use App\Models\User;
Gate::after(function (User $user, string $ability, bool|null $result, mixed $arguments) {
if ($user->isAdministrator()) {
return true;
}
});
I valori restituiti dalle closure after
non sovrascriveranno il risultato del controllo di autorizzazione a meno che il gate o la policy non abbiano restituito null
.
Autorizzazione Inline
A volte potresti voler determinare se l’utente attualmente autenticato è autorizzato a eseguire una determinata azione senza scrivere una gate dedicata corrispondente all’azione. Laravel ti permette di effettuare questi tipi di controlli di autorizzazione "inline" tramite i metodi Gate::allowIf
e Gate::denyIf
. L’autorizzazione inline non esegue nessuno dei "hook di autorizzazione before o after":
use App\Models\User;
use Illuminate\Support\Facades\Gate;
Gate::allowIf(fn (User $user) => $user->isAdministrator());
Gate::denyIf(fn (User $user) => $user->banned());
Se l’azione non è autorizzata o se nessun utente è attualmente autenticato, Laravel lancerà automaticamente un’eccezione Illuminate\Auth\Access\AuthorizationException
. Le istanze di AuthorizationException
vengono automaticamente convertite in una risposta HTTP 403 dal gestore delle eccezioni di Laravel.
Creare Policy
Generating Policies
Le Policies sono classi che organizzano la logica di autorizzazione attorno a un particolare modello o risorsa. Ad esempio, se la tua applicazione è un blog, potresti avere un modello App\Models\Post
e una corrispondente App\Policies\PostPolicy
per autorizzare azioni degli utenti come creare o aggiornare i post.
Puoi generare una policy utilizzando il comando Artisan make:policy
. La policy generata verrà posizionata nella directory app/Policies
. Se questa directory non esiste nella tua applicazione, Laravel la creerà automaticamente:
php artisan make:policy PostPolicy
Il comando make:policy
genererà una classe policy vuota. Se desideri generare una classe con metodi di policy di esempio relativi alla visualizzazione, creazione, aggiornamento e cancellazione della risorsa, puoi aggiungere l’opzione --model
durante l’esecuzione del comando:
php artisan make:policy PostPolicy --model=Post
Registrazione delle Policy
Policy Discovery
Per impostazione predefinita, Laravel scopre automaticamente le policy purché il modello e la policy seguano le convenzioni standard di denominazione di Laravel. In particolare, le policy devono trovarsi in una directory Policies
all’interno o al di sopra della directory che contiene i tuoi modelli. Ad esempio, i modelli possono essere posizionati nella directory app/Models
mentre le policy possono essere posizionate nella directory app/Policies
. In questa situazione, Laravel cercherà le policy in app/Models/Policies
e poi in app/Policies
. Inoltre, il nome della policy deve corrispondere al nome del modello e avere il suffisso Policy
. Quindi, un modello User
corrisponderebbe a una classe di policy UserPolicy
.
Se desideri definire la tua logica di scoperta delle policy, puoi registrare una callback personalizzata per la scoperta delle policy utilizzando il metodo Gate::guessPolicyNamesUsing
. Tipicamente, questo metodo dovrebbe essere chiamato dal metodo boot
del AppServiceProvider
della tua applicazione:
use Illuminate\Support\Facades\Gate;
Gate::guessPolicyNamesUsing(function (string $modelClass) {
// Return the name of the policy class for the given model...
});
Registrazione Manuale delle Policies
Usando la facade Gate
, puoi registrare manualmente le policies e i rispettivi modelli all’interno del metodo boot
del AppServiceProvider
della tua applicazione:
use App\Models\Order;
use App\Policies\OrderPolicy;
use Illuminate\Support\Facades\Gate;
/**
* Bootstrap any application services.
*/
public function boot(): void
{
Gate::policy(Order::class, OrderPolicy::class);
}
Scrivere Policies
Metodi della Policy
Una volta registrata la classe della policy, puoi aggiungere metodi per ogni azione che autorizza. Ad esempio, definiamo un metodo update
nella nostra PostPolicy
che determina se un determinato App\Models\User
può aggiornare una specifica istanza di App\Models\Post
.
Il metodo update
riceverà come argomenti un’istanza di User
e una di Post
, e dovrebbe restituire true
o false
indicando se l’utente è autorizzato ad aggiornare il Post
dato. Quindi, in questo esempio verificheremo che l’id
dell’utente corrisponda al user_id
del post:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* Determina se il post dato può essere aggiornato dall'utente.
*/
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}
Puoi continuare a definire ulteriori metodi nella policy secondo necessità per le varie azioni che autorizza. Ad esempio, potresti definire i metodi view
o delete
per autorizzare diverse azioni relative ai Post
, ma ricorda che sei libero di dare alla tua policy qualsiasi nome tu voglia per i metodi.
Se hai utilizzato l’opzione --model
quando hai generato la tua policy tramite la console Artisan, conterrà già i metodi per le azioni viewAny
, view
, create
, update
, delete
, restore
e forceDelete
.
Tutte le policy vengono risolte tramite il service container di Laravel, permettendo di indicare qualsiasi dipendenza necessaria nel costruttore della policy per averla iniettata automaticamente.
Risposte delle Policy
Finora, abbiamo esaminato solo i metodi delle policy che restituiscono valori booleani semplici. Tuttavia, a volte potresti voler restituire una risposta più dettagliata, inclusa un messaggio di errore. Per fare ciò, puoi restituire un’istanza di Illuminate\Auth\Access\Response
dal tuo metodo di policy:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* Determina se il post dato può essere aggiornato dall'utente.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::deny('Non possiedi questo post.');
}
Quando restituisci una risposta di autorizzazione dalla tua policy, il metodo Gate::allows
restituirà comunque un valore booleano semplice; tuttavia, puoi utilizzare il metodo Gate::inspect
per ottenere la risposta completa di autorizzazione restituita dal gate:
use Illuminate\Support\Facades\Gate;
$response = Gate::inspect('update', $post);
if ($response->allowed()) {
// L'azione è autorizzata...
} else {
echo $response->message();
}
Quando usi il metodo Gate::authorize
, che lancia un AuthorizationException
se l’azione non è autorizzata, il messaggio di errore fornito dalla risposta di autorizzazione sarà propagato alla risposta HTTP:
Gate::authorize('update', $post);
// L'azione è autorizzata...
Personalizzare lo Stato della Risposta HTTP
Quando un’azione viene negata tramite un metodo di policy, viene restituita una risposta HTTP 403
; tuttavia, a volte può essere utile restituire un codice di stato HTTP alternativo. Puoi personalizzare il codice di stato HTTP restituito per un controllo di autorizzazione fallito utilizzando il costruttore statico denyWithStatus
sulla classe Illuminate\Auth\Access\Response
:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* Determina se il post dato può essere aggiornato dall'utente.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyWithStatus(404);
}
Poiché nascondere le risorse tramite una risposta 404
è uno schema molto comune nelle applicazioni web, viene offerto il metodo denyAsNotFound
per comodità:
use App\Models\Post;
use App\Models\User;
use Illuminate\Auth\Access\Response;
/**
* Determina se il post dato può essere aggiornato dall'utente.
*/
public function update(User $user, Post $post): Response
{
return $user->id === $post->user_id
? Response::allow()
: Response::denyAsNotFound();
}
Metodi senza Model
Alcuni metodi di policy ricevono solo un’istanza dell’user attualmente autenticato. Questa situazione è più comune quando si autorizzano azioni di create
. Per esempio, se stai creando un blog, potresti voler determinare se un user è autorizzato a creare post. In queste situazioni, il tuo metodo di policy dovrebbe aspettarsi di ricevere solo un’istanza di user:
/**
* Determine if the given user can create posts.
*/
public function create(User $user): bool
{
return $user->role == 'writer';
}
Utenti Ospiti
Per impostazione predefinita, tutte le gate e le policies restituiscono automaticamente false
se la richiesta HTTP in arrivo non è stata avviata da un utente autenticato. Tuttavia, puoi permettere che questi controlli di autorizzazione passino attraverso le tue gate e policies dichiarando un tipo di hint "opzionale" o fornendo un valore predefinito null
per la definizione dell’argomento user:
<?php
namespace App\Policies;
use App\Models\Post;
use App\Models\User;
class PostPolicy
{
/**
* Determina se il post dato può essere aggiornato dall'utente.
*/
public function update(?User $user, Post $post): bool
{
return $user?->id === $post->user_id;
}
}
Filtri di Policy
Per alcuni utenti, potresti voler autorizzare tutte le azioni all’interno di una determinata policy. Per fare ciò, definisci un metodo before
nella policy. Il metodo before
verrà eseguito prima di qualsiasi altro metodo nella policy, offrendoti l’opportunità di autorizzare l’azione prima che il metodo della policy previsto venga effettivamente chiamato. Questa funzionalità è più comunemente utilizzata per autorizzare gli amministratori dell’applicazione a eseguire qualsiasi azione:
use App\Models\User;
/**
* Esegui controlli preliminari di autorizzazione.
*/
public function before(User $user, string $ability): bool|null
{
if ($user->isAdministrator()) {
return true;
}
return null;
}
Se desideri negare tutti i controlli di autorizzazione per un particolare tipo di utente, puoi restituire false
dal metodo before
. Se viene restituito null
, il controllo di autorizzazione passerà al metodo della policy.
Il metodo
before
di una classe policy non verrà chiamato se la classe non contiene un metodo con un nome che corrisponde al nome dell’abilità che viene controllata.
Autorizzare le Azioni con le Policy
Tramite il Modello User
Il modello App\Models\User
incluso nella tua applicazione Laravel dispone di due metodi utili per autorizzare le azioni: can
e cannot
. I metodi can
e cannot
accettano il nome dell’azione che desideri autorizzare e il modello pertinente. Ad esempio, verifichiamo se un utente è autorizzato ad aggiornare un determinato modello App\Models\Post
. Tipicamente, questo viene fatto all’interno di un metodo del controller:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Aggiorna il post fornito.
*/
public function update(Request $request, Post $post): RedirectResponse
{
if ($request->user()->cannot('update', $post)) {
abort(403);
}
// Aggiorna il post...
return redirect('/posts');
}
}
Se una policy è registrata per il modello in questione, il metodo can
chiamerà automaticamente la policy appropriata e restituirà il risultato booleano. Se non è registrata alcuna policy per il modello, il metodo can
cercherà di chiamare il Gate basato su closure corrispondente al nome dell’azione fornita.
Azioni che non Richiedono Modelli
Ricorda, alcune azioni possono corrispondere a metodi della policy come create
che non richiedono un’istanza del modello. In queste situazioni, puoi passare un nome di classe al metodo can
. Il nome della classe verrà utilizzato per determinare quale policy usare durante l’autorizzazione dell’azione:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
class PostController extends Controller
{
/**
* Crea un post.
*/
public function store(Request $request): RedirectResponse
{
if ($request->user()->cannot('create', Post::class)) {
abort(403);
}
// Crea il post...
return redirect('/posts');
}
}
Tramite la Facade Gate
Oltre ai metodi utili forniti al modello App\Models\User
, puoi sempre autorizzare azioni tramite il metodo authorize
della facade Gate
.
Come il metodo can
, questo metodo accetta il nome dell’azione che desideri autorizzare e il modello pertinente. Se l’azione non è autorizzata, il metodo authorize
lancerà un’eccezione Illuminate\Auth\Access\AuthorizationException
che il gestore delle eccezioni di Laravel convertirà automaticamente in una risposta HTTP con un codice di stato 403:
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
class PostController extends Controller
{
/**
* Aggiorna il post del blog fornito.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
Gate::authorize('update', $post);
// L'utente corrente può aggiornare il post del blog...
return redirect('/posts');
}
}
Azioni che non richiedono modelli
Come discusso in precedenza, alcuni metodi di policy come create
non richiedono un’istanza di modello. In questi casi, dovresti passare il nome della classe al metodo authorize
. Il nome della classe verrà utilizzato per determinare quale policy usare quando autorizzi l’azione:
use App\Models\Post;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Gate;
/**
* Crea un nuovo post nel blog.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function create(Request $request): RedirectResponse
{
Gate::authorize('create', Post::class);
// L'utente corrente può creare post nel blog...
return redirect('/posts');
}
Tramite Middleware
Laravel include un middleware che può autorizzare azioni prima che la richiesta in arrivo raggiunga le tue route o controller. Di default, il middleware Illuminate\Auth\Middleware\Authorize
può essere associato a una route utilizzando l’alias can
middleware alias, registrato automaticamente da Laravel. Vediamo un esempio di utilizzo del middleware can
per autorizzare che un utente possa aggiornare un post:
use App\Models\Post;
Route::put('/post/{post}', function (Post $post) {
// L'utente corrente può aggiornare il post...
})->middleware('can:update,post');
In questo esempio, stiamo passando al middleware can
due argomenti. Il primo è il nome dell’azione che vogliamo autorizzare e il secondo è il parametro della route che vogliamo passare al metodo della policy. In questo caso, poiché stiamo usando il binding implicito dei modelli, un modello App\Models\Post
verrà passato al metodo della policy. Se l’utente non è autorizzato a eseguire l’azione data, il middleware restituirà una risposta HTTP con un codice di stato 403.
Per comodità, puoi anche associare il middleware can
alla tua route utilizzando il metodo can
:
use App\Models\Post;
Route::put('/post/{post}', function (Post $post) {
// L'utente corrente può aggiornare il post...
})->can('update', 'post');
Azioni che non richiedono modelli
Alcuni metodi di policy, come create
, non necessitano di un’istanza di modello. In questi casi, puoi passare il nome della classe al middleware. Il nome della classe verrà usato per determinare quale policy applicare durante l’autorizzazione dell’azione:
Route::post('/post', function () {
// L'utente corrente può creare post...
})->middleware('can:create,App\Models\Post');
Specificare l’intero nome della classe all’interno di una definizione middleware come stringa può diventare complicato. Per questo motivo, puoi scegliere di collegare il middleware can
alla tua route usando il metodo can
:
use App\Models\Post;
Route::post('/post', function () {
// L'utente corrente può creare post...
})->can('create', Post::class);
Via Template Blade
Quando scrivi i template Blade, potresti voler mostrare una parte della pagina solo se l’utente è autorizzato a eseguire una determinata azione. Ad esempio, potresti voler mostrare un modulo di aggiornamento per un post del blog solo se l’utente può effettivamente aggiornare il post. In questa situazione, puoi usare le direttive @can
e @cannot
:
@can('update', $post)
<!-- L'utente corrente può aggiornare il post... -->
@elsecan('create', App\Models\Post::class)
<!-- L'utente corrente può creare nuovi post... -->
@else
<!-- ... -->
@endcan
@cannot('update', $post)
<!-- L'utente corrente non può aggiornare il post... -->
@elsecannot('create', App\Models\Post::class)
<!-- L'utente corrente non può creare nuovi post... -->
@endcannot
Queste direttive sono scorciatoie comode per scrivere istruzioni @if
e @unless
. Le istruzioni @can
e @cannot
sopra sono equivalenti alle seguenti istruzioni:
@if (Auth::user()->can('update', $post))
<!-- L'utente corrente può aggiornare il post... -->
@endif
@unless (Auth::user()->can('update', $post))
<!-- L'utente corrente non può aggiornare il post... -->
@endunless
Puoi anche determinare se un utente è autorizzato a eseguire qualsiasi azione da un dato array di azioni. Per fare ciò, usa la direttiva @canany
:
@canany(['update', 'view', 'delete'], $post)
<!-- L'utente corrente può aggiornare, visualizzare o eliminare il post... -->
@elsecanany(['create'], \App\Models\Post::class)
<!-- L'utente corrente può creare un post... -->
@endcanany
Azioni che non richiedono modelli
Come la maggior parte degli altri metodi di autorizzazione, puoi passare un nome di classe alle direttive @can
e @cannot
se l’azione non richiede un’istanza del modello:
@can('create', App\Models\Post::class)
<!-- L'utente corrente può creare post... -->
@endcan
@cannot('create', App\Models\Post::class)
<!-- L'utente corrente non può creare post... -->
@endcannot
Fornire Contesto Aggiuntivo
Quando si autorizzano azioni utilizzando le policies, è possibile passare un array come secondo argomento alle varie funzioni e helper di autorizzazione. Il primo elemento dell’array verrà utilizzato per determinare quale policy debba essere invocata, mentre gli altri elementi dell’array vengono passati come parametri al metodo della policy e possono essere utilizzati per fornire contesto aggiuntivo durante le decisioni di autorizzazione. Ad esempio, considera la seguente definizione del metodo PostPolicy
che contiene un parametro aggiuntivo $category
:
/**
* Determine if the given post can be updated by the user.
*/
public function update(User $user, Post $post, int $category): bool
{
return $user->id === $post->user_id &&
$user->canUpdateCategory($category);
}
Quando si tenta di determinare se l’utente autenticato può aggiornare un determinato post, possiamo invocare questo metodo della policy in questo modo:
/**
* Update the given blog post.
*
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
public function update(Request $request, Post $post): RedirectResponse
{
Gate::authorize('update', [$post, $request->category]);
// The current user can update the blog post...
return redirect('/posts');
}
Autorizzazione & Inertia
Anche se l’autorizzazione deve sempre essere gestita sul server, può spesso essere comodo fornire alla tua applicazione frontend i dati di autorizzazione per rendere correttamente l’interfaccia utente della tua applicazione. Laravel non definisce una convenzione obbligatoria per esporre le informazioni di autorizzazione a un frontend basato su Inertia.
Tuttavia, se stai utilizzando uno dei starter kit basati su Inertia di Laravel, la tua applicazione contiene già un middleware HandleInertiaRequests
. All’interno del metodo share
di questo middleware, puoi restituire dati condivisi che saranno forniti a tutte le pagine Inertia della tua applicazione. Questi dati condivisi possono servire come posizione comoda per definire le informazioni di autorizzazione per l’utente:
<?php
namespace App\Http\Middleware;
use App\Models\Post;
use Illuminate\Http\Request;
use Inertia\Middleware;
class HandleInertiaRequests extends Middleware
{
// ...
/**
* Definisci le proprietà condivise di default.
*
* @return array<string, mixed>
*/
public function share(Request $request)
{
return [
...parent::share($request),
'auth' => [
'user' => $request->user(),
'permissions' => [
'post' => [
'create' => $request->user()->can('create', Post::class),
],
],
],
];
}
}