Sconto del 20% su tutti i corsi inserendo nel form il codice SPRING20 | Fino al 30 aprile
Sconto del 20% su tutti i corsi inserendo nel form il codice SPRING20 | Fino al 30 aprile

Guide per aspiranti programmatori

Lezione 22 / 30

Eloquent e Mass Assignment in Laravel

I vantaggi di usare i Model di Eloquent in una applicazione Laravel sono molteplici. Rispettando alcune buone regole sulla nomenclatura di tabelle e colonne del database, è possibile accedere direttamente dal proprio codice a tali dati senza dover scrivere codice necessario a convertire elementi del database in classi e relative property.

Nelle lezioni precedenti abbiamo, principalmente, visto quanto offerto dal framework per la lettura di informazioni dal database, ma (per?) un’ applicazione avr(em)ò sicuramente necessità di scrivere anche nuove righe a fronte di un input dell’utente.

Eloquent mette a disposizione metodi specifici per gestire in modo corretto, sicuro e veloce la scrittura di info tramite Model Eloquent.

Model e salvataggio di informazioni in Laravel

Abbiamo visto come i Model eloquent permettono di usare un’istanza del model stesso per inserire nuovi dati o modificare dati esistenti usando le property dinamiche legate alle colonne su database.

use App\Model\Author;
use App\Model\Book;

$author = $author = Author::where('name', 'Randal Munroe')->first();

$book = new Book;

$book->title = "What If?"
$book->author_id = $author->id;
// ...

$book->save();

Anche se il metodo save inserisce automaticamente data di creazione e modifica, nel caso di model con molte property potrebbe diventare scomodo impostare una a una le varie property dinamiche alla creazione di una nuova riga.

È disponibile, in alternativa, il metodo create che accetta un array chiave/valore di tutte le property da cambiare e i rispettivi valori.

use App\Model\Book;

// ...

Book::create([
  'title' => 'What If?',
  'author_id' => $author->id,
  'isbn_13' => '978-0544272996',
  'published_at' => '2014-09-02',
  // ..
]);

Esiste un metodo analogo per l’aggiornamento di record già presenti su database, update.

use App\Model\Book;

// ...

Book::where('isbn_13', '978-0544272996')->update([
  'price' => '27,50/EUR',
  'available' => true,
]);

L’utilizzo di questi due metodi presenta vantaggi e svantaggi. Da un lato, infatti, le azioni di creazione di un nuovo record e di update sono più chiaramente leggibili e “compatte” rispetto all’assegnare singolarmente valori alle singole property. Inoltre, non è necessario chiamare esplicitamente il metodo save per far persistere effettivamente i dati sul database (lato “codice” abbiamo un’ istanza che rappresenta un record su database).

Dall’altro, la possibilità di assegnare un valore a tutte le colonne del database pone interessanti questioni di sicurezza. Se provassimo ad eseguire la create nell’esempio precedente in una versione recente di Laravel, riceveremmo un errore.

Illuminate\Database\Eloquent\MassAssignmentException Add [name] to fillable property to allow mass assignment on [App\Models\Author].

Vulnerabilità “mass assignment” in Laravel

Si parla di vulnerabilità mass assignment in Laravel nel caso in cui le richieste HTTP che una applicazione web riceve vengono mappate automaticamente in variabili o oggetti all’interno del proprio codice. Questo legame tra richiesta HTTP e dati interni all’applicazione potrebbe causare problemi o danni.

Facciamo un esempio pratico e ipotetico. Nella nostra applicazione Laravel abbiamo la tabella users con le colonne email, password e role che indica se l’utente è visualizzatore, editor o admin dell’applicazione stessa. La tabella è connessa a un Model che, a sua volta, è connesso a un Controller che, a sua volta, riceve richieste di signup da un Form. Per creare un nuovo utente, esiste un form html e una metodo store in un controller.

<form>
  <input name="password" type="text">
  <input name="email" text="text">
  <input type="submit">
</form>
use App\Model\User;

public function store(UserFormRequest $request)
{
  $user = User::create($request->validated());
}

In questa situazione, i dati che arrivano dal form potrebbero essere convertiti automaticamente dal form (html) all’array da passare alla create, finendo, quindi, su database. Se il mapping fosse automatico e basato sulla corrispondenza dei vari nomi delle entità, un utente mavolo potrebbe forzare il form lato HTML, aggiungere un role ed essere automaticamente aggiunto con il role di admin.

Questo tipo di vulnerabilità è dovuta a una serie di automatismi legati a convenzioni sui nomi che causano un legame diretto tra dato sul database e dato nel browser dell’utente, in gran parte introdotto per rendere più semplice la vita degli sviluppatori.

In un applicativo Laravel è possibile applicare metodi di protezione basati su allow-list o su block-list, implementabili a livello di model tramite opportune property: $fillable e $guarded.

Property fillable e property guarded in Laravel

I meccanismi di allow-list e block-list sono regolati in un Model Eloquent tramite la variabile $fillable e la variabile $guarded.

Poiché ogni modello Eloquent creato nella nostra applicazione estende la classe Illuminate\Database\Eloquent\Model, se non specificato altrimenti ogni modello assumerà per queste due variabili i seguenti valori (nessuna fillable, tutte guarded):

$fillable = [];

$guarded = ['*'];

Nei due array php è possibile indicare i nomi delle colonne della tabella associata con effetto opposto. Le colonne elencate in $fillable potranno essere usate come chiavi nell’array passato a una create, le colonne elencate in $guarded verranno ignorate, anche se passate alla create.

Se, quindi, volessimo proteggere la nostra ipotetica tabella users con un metodo allow-list potremmo modificare il nostro model indicando:

class User extends Model
{
  protected $fillable= ['email', 'password'];

  // ...
}

Se, invece, preferiamo l’approccio black-list, allora va indicata solo la colonna da non scrivere:

class User extends Model
{
    protected $guarded = ['role'];
    // ...
}

Le property $fillable e $guarded intervengono, ovviamente, come misura di sicurezza per il mass assignment; sarà comunque possibile usare il model e i suoi altri meccanismi per scrivere anche la colonna role nella gestione di quelle richieste che sono autorizzate a modificare il suo valore.

NOTA: è possibile scegliere solo uno dei due approcci, non è possibile cambiare valore per sia per $fillable che per $guarded insieme in un model.

Pagamento rateale

Valore della rata: A PARTIRE DA 115 €/mese.

Esempio di finanziamento 

Importo finanziato: € 2440 in 24 rate da € 115 – TAN fisso 9,55% TAEG 12,57% – importo totale del credito € 2841.

Il costo totale del credito comprende: interessi calcolati al TAN indicato, oneri fiscali (imposta di bollo sul contratto 16,00 euro*) addebitati sulla prima rata, costo mensile di gestione pratica € 3,90, spesa di istruttoria € 0,00, spesa per invio rendicontazione periodica cartacea € 0,98 (o spesa per invio rendicontazione periodica cartacea € 0,00), imposta di bollo su rendicontazione periodica € 0,00. Modalità di rimborso obbligatoria: addebito diretto su c/c. La scadenza delle rate è determinata dal giorno della liquidazione del contratto; la data di scadenza delle rate è prevista il giorno 15 del mese. L’importo di ciascuna rata comprende una quota di capitale crescente e interessi decrescente secondo un piano di ammortamento “alla francese”. Offerta valida dal 01/01/2024 al 31/12/2024.

Messaggio pubblicitario con finalità promozionale. Per le informazioni precontrattuali richiedere sul punto vendita il documento “Informazioni europee di base sul credito ai consumatori” (SECCI) e copia del testo contrattuale. Salvo approvazione di Sella Personal Credit S.p.A. Aulab S.r.l. opera quale intermediario del credito NON in esclusiva.

*In fase di richiesta del finanziamento verrà proposta la facoltà di selezionare, in alternativa all’imposta di bollo sul contratto di 16,00 euro, l’imposta sostitutiva, pari allo 0,25% dell’importo finanziato.

Pagamento rateale

Valore della rata: A PARTIRE DA 210 €/mese.

Esempio di finanziamento  

Importo finanziato: € 4500 in 24 rate da € 210,03 – TAN fisso 9,68% TAEG 11,97% – importo totale del credito € 5146,55.

Il costo totale del credito comprende: interessi calcolati al TAN indicato, oneri fiscali (imposta di bollo sul contratto 16,00 euro*) addebitati sulla prima rata, costo mensile di gestione pratica € 3,90, spesa di istruttoria € 0,00, spesa per invio rendicontazione periodica cartacea € 0,98 (o spesa per invio rendicontazione periodica cartacea € 0,00), imposta di bollo su rendicontazione periodica € 0,00. Modalità di rimborso obbligatoria: addebito diretto su c/c. La scadenza delle rate è determinata dal giorno della liquidazione del contratto; la data di scadenza delle rate è prevista il giorno 15 del mese. L’importo di ciascuna rata comprende una quota di capitale crescente e interessi decrescente secondo un piano di ammortamento “alla francese”. Offerta valida dal 01/01/2024 al 31/12/2024.

Messaggio pubblicitario con finalità promozionale. Per le informazioni precontrattuali richiedere sul punto vendita il documento “Informazioni europee di base sul credito ai consumatori” (SECCI) e copia del testo contrattuale. Salvo approvazione di Sella Personal Credit S.p.A. Aulab S.r.l. opera quale intermediario del credito NON in esclusiva.

* In fase di richiesta del finanziamento verrà proposta la facoltà di selezionare, in alternativa all’imposta di bollo sul contratto di 16,00 euro, l’imposta sostitutiva, pari allo 0,25% dell’importo finanziato.

Contattaci senza impegno per informazioni sul corso

Scopriamo insieme se i nostri corsi fanno per te. Compila il form e aspetta la chiamata di uno dei nostri consulenti.