2

La prima volta che mi sono imbattuto in un nonce sono andato nel panico, cos’era quel codice che veniva passato da WordPress ad ogni richiesta e che cambiava ogni volta?

Nella domanda mi ero dato già dato la risposta… Cercando su wikipedia:

In crittografia il termine nonce indica un numero, generalmente casuale o pseudo-casuale, che ha un utilizzo unico. Nonce è infatti la contrazione delle parole inglese number used once, che significano appunto “numero usato solo una volta”.

In realtà i nonce di WordPress non sono esattamente tali in quanto possono essere usati più di una volta nel corso di 12 ore ed il loro valore temporale può essere esteso anche oltre quella soglia… ma cerchiamo di capire come funzionano.

Ogni volta che c’è un’interazione da parte dell’utente, con una richiesta $_GET o $_POST, non si può essere certi di quale sia la fonte della richiesta e se l’utente sia abilitato ad effettuare tale operazione.

Certo, un check delle capability è sempre apprezzato ma il nonce aggiunge quel livello di sicurezza in più, che mancava, ad esempio, nelle prime versioni di WordPress, quando il controllo veniva effettuato solo sul referer (la pagina di origine).

Prima di spiegare esattamente come funzionino i nonce di WordPress vediamo un pò di codice, in modo da non annoiarvi…

<?php
// Creo il codice
$nonce = wp_create_nonce( 'say-hello' );
// e lo applico all'url
?>
<a href="myplugin.php?_wpnonce=<?php echo $nonce ?>">Say Hello!</a>

Il codice sopra non fa altro che creare un codice nonce ed applicarlo all’url in modo che la pagina myplugin.php possa fidarsi ed effettuare l’operazione richiesta.

Nella pagina myplugin.php, invece, avremo il seguente codice di controllo:

<?php
// Prendo il codice
$nonce = $_GET['_wpnonce'];
// e lo verifico
if ( wp_verify_nonce( $nonce, 'say-hello' ) ){
    // Il codice è corretto quindi...
    echo 'Hellooo!!!';
} else {
    die( 'Good bye!' );
}

Che non fa altro che prendere il codice e verificarne la genuinità.

Se si fosse trattato di fare l’echo in un post specifico avremmo potuto rendere il codice ancora più sicuro affiancando a say-hello il post ID come da esempio che segue:

<?php
global $post;
$nonce = wp_create_nonce( 'say-hello' . $post->ID );

// E dall'altra parte
global $post;
if ( wp_verify_nonce( $_GET['_wpnonce'], 'say-hello' . $post->ID ) ){
    echo 'Hellooo!!!';
} else {
    die( 'Good bye!' );
}
?>

Andiamo a vedere nel dettaglio cosa fa wp_create_nonce( $action )

  • Immagazzina i dati dell’utente;
  • Immagazzina i dati dell’azione;
  • Codifica i dati immagazzinati, usando una chiave unica propria dell’installazione WordPress, in un codice dalla validità temporale di 12 ore.

In parole povere, anche ammettendo che un terzo riesca a trafugare un codice nonce che vi appartiene potrà adoperarlo nell’arco delle 12 ore, a patto che abbia le vostre credenziali utente, solo per effettuare un’azione ben specifica, come dire ciao in un singolo post di un singolo blog!

Se non fosse abbastanza gli sviluppatori di WordPress ci mettono a disposizione tutta una serie di funzioni di supporto per aiutarci ad usare i nonce nei nostri temi e plugin…

<?php wp_nonce_url( $url, $action ); ?>

Il codice sopra, ad esempio, aggiunge in automatico il nonce all’url e ne fa l’echo.

<?php wp_nonce_field( $action, $name, $referer, $echo ); ?>

Questo, invece, fa in automatico l’echo di un input field nascosto che contiene il nostro nonce per la validazione dei form. Nel dettaglio $action è l’azione che vogliamo compiere, $name il name del campo ( per default _wpnonce ), $referer (true/false) definisce se aggiungere anche un campo che contenga il referer ed infine $echo definisce se farne l’echo o ritornarne l’output.

<?php check_admin_referer( $action, $query_arg ); ?>

Infine, check_admin_referer(), permette di fare la verifica del nonce in automatico (sia tramite richieste $_GET che $_POST).

Per una guida completa, in inglese, all’uso dei nonce vi rimando, come al solito, al codex di WordPress.

Spero che la mia esposizione risulti chiara, l’argomento è semplice ma si cade facilmente in trappola nell’uso di inglesismi… Per qualsiasi dubbio, comunque, esistono i commenti!

  1. Non ho capito una cosa: supponiamo che io voglia mandare un form con AJAX (POST) da una pagina WP. L’action del post è il tuo plugin.php.

    Il plugin.php me lo immagino come un file separato da WP: il file può eseguire il codice WP qui sotto?

    wp_verify_nonce( $nonce, ‘say-hello’ );

    Oppure plugin.php deve essere inserito in qualche dir specifica?

    1. Buongiorno Gabri,

      Dipende se lato server vuoi rispondere alla richiesta del form da un plugin o dal tema. Nel primo caso devi creare un plugin di WordPress (qua trovi tutte le informazioni necessarie: https://codex.wordpress.org/Writing_a_Plugin) nel secondo puoi inserire il codice nel file functions.php all’interno della cartella del tema in uso (o in un child-theme se vuoi mantenere la possibilità di aggiornare il tema). In ogni caso negli esempi in questione manca tutta la parte di codice relativa alla gestione del form per cui non può essere usato così com’è.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *