WordPress AJAX mit Nonce sichern

WP beschreibt Nonce wie folgt: Nonce ist eine «einmalig verwendete Zeichenkette», die dazu dient, URLs und Formulare vor Missbrauch zu schützen. WordPress-Nonce ist ein Hash, der sich aus Zahlen und Buchstaben zusammensetzt. Nonce wird einmal verwendet und hat eine begrenzte «Lebensdauer».

Im folgenden beschreibe ich zwei verschiedene Methoden, wie man eine AJAX-Anfrage mit Nonce absichert.

1. Nonce zum DOM hinzufügen

Zuerst fügen wir unsere js-Datei korrekt mit wp_enqueue_script() hinzu:

 function ud_theme_name_scripts() {
     wp_enqueue_script( 'script-name', get_stylesheet_directory_uri().
         '/js/ajax-file.js', array(), '1.0.0', true );
 }
 add_action( 'wp_enqueue_scripts', 'ud_theme_name_scripts' );

Bei dieser Methode schreiben wir Nonce in das DOM und lesen den Schlüssel später mit jQuery wieder aus. Der dafür verwendete Container soll im Footer erscheinen, dafür wird der Hook wp_footer verwendet:

function ud_add_nonce() {
  /* Nonce erzeugen */
  $nonce = wp_create_nonce( 'ud-ajax-nonce' );
  /* Leerer div-Container mit data-Attribut ausgeben */
  echo '<div id="ud-nonce" data-nonce="' . esc_attr( $nonce ) . '"></div>';
}
add_action('wp_footer', 'ud_add_nonce');

Der erzeugte Nonce-Schlüssel wird als Attribut des Elements #ud-nonce in das DOM eingefügt. Das data-Attribut wird bei der AJAX-Anfrage mit jQuery( '#ud-nonce' ).data( 'nonce' ) übergeben:

$.ajax({
  type: "POST",          // use $_POST request to submit data
  url: ud_ajax_url,      // URL to "wp-admin/admin-ajax.php"
  data: {
    action: 'ud_ajax_callback', // wp_ajax_*, wp_ajax_nopriv_*
    security: jQuery( '#ud-nonce' ).data( 'nonce' ), // PHP: $_POST['security']
    vorname: 'ulrich', // PHP: $_POST['vorname']
    nachname: 'digital', // PHP: $_POST['nachname']
  },
  success:function( data ) {
    $( '#ulrichdigital' ).html( data );
  },
  error: function() {
    console.log(errorThrown); // error
  }
});

Der Schlüssel wird übertragen und kann im AJAX-Callback mit wp_verify_nonce( $_POST['security'], 'ajax_nonce' ); überprüft werden:

/**
 * Ajax Callback
 */
function ud_ajax_callback(){
 
  /* Nonce prüfen */
  if ( ! wp_verify_nonce( $_POST['security'], 'ajax_nonce' ) ) {
    wp_die( 'Nonce ist ungültig!' );
  } // endif

  /* Get request */
  $vorname = isset( $_POST['vorname'] ) ? $_POST['vorname'] : 'N/A';
  $nachname = isset( $_POST['nachname'] ) ? $_POST['nachname'] : 'N/A';
  
  echo '<p>Hello. Dein Vorname ist ' . strip_tags( $vorname ) . '.</p>';
  echo 'Dein Nachame ist ' . strip_tags( $nachname ) . '.</p>';
  
  wp_die(); // benötigt um die AJAX-Anfrage zu beenden
}

Wir verwenden wp_ajax_nopriv_ und wp_ajax_ um die Funktion mit den WordPress-Hooks zu verbinden:

 add_action('wp_ajax_nopriv_ud_ajax_callback', 'ud_ajax_callback');    
 add_action('wp_ajax_ud_ajax_callback', 'ud_ajax_callback');

Der Hook wp_ajax_ud_ajax_callback wird ausgelöst, wenn ein Benutzer eingeloggt ist, und wp_ajax_nopriv_ud_ajax_callback, wenn er es nicht ist.

2. Nonce über Localize Script hinzufügen

Die zweite Methode ist per wp_localize_script(). Diese Funktion erlaubt es auch einen Array zu übergeben.

Wir verwenden demnach wp_localize_script(), um Nonce einen Schlüssel zu übergeben:

add_action( 'wp_enqueue_scripts', 'ud_ajax_script' );
 
function ud_ajax_script() {
  wp_register_script( 'ud-wp-ajax-script', get_stylesheet_directory_uri() . "js/ud-ajax-script.js", array( 'jquery' ), '1.0.0', true );
 
  /* Skript-Daten lokalisieren */
  $ud_ajax_data = array(
    'url'   => admin_url( 'admin-ajax.php' ),
    'nonce' => wp_create_nonce( 'ud-ajax-nonce' ),
  );
 
  /* Daten als JS var über Localize Script senden */
  wp_localize_script( 'ud-ajax-script', 'ud_ajax_data', $ud_ajax_data  );
}

Damit ist das Skript erfolgreich registriert und lokalisiert. Bei der AJAX-Anfrage bekommt security mit ud_ajax_data.nonce den erzeugten Schlüssel mit:

$.ajax({
    type: "POST",                        // use $_POST request to submit data
    url: ud_ajax_data.url,               // URL to "wp-admin/admin-ajax.php"
    data: {
        action     : 'ud_sayhello',      // wp_ajax_*, wp_ajax_nopriv_*
        security   : ud_ajax_data.nonce,
        vorname    : 'ulrich',           // PHP: $_POST['vorname']
        nachname   : 'digital',          // PHP: $_POST['nachname']
    },
    success:function( data ) {
        $( '#ud-callback' ).html( data );
    },
    error: function(){
        console.log(errorThrown); // error
    }
});

Im Callback wird der Schlüssel mit wp_verify_nonce geprüft und mit «erwischt!» beendet, falls die Schlüssel nicht übereinstimmen:

// Check for nonce security      
if ( ! wp_verify_nonce( $_POST['security'], 'ajax-nonce' ) ) {
  wp_die ( 'erwischt!');
}

Der Rückgabewert (int|false) der Funktion ist im Übrigen wie folgt:
1 wenn Nonce gültig ist und vor 0-12 Stunden erzeugt wurde
2 wenn Nonce gültig ist und vor 12-24 Stunden erzeugt wurde
false wenn Nonce ungültig ist

1 Star2 Stars3 Stars4 Stars5 Stars (1)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert