wp_verify_nonce continua a fallire - Risoluzione

11 set 2013, 17:09:59
Visualizzazioni: 14.1K
Voti: 0

Dovevo assegnare categorie ai post dal frontend, quindi sto utilizzando la soluzione suggerita in questo thread, sotto forma di plugin. Funziona come previsto, ma volevo aggiungere un campo nonce per renderlo più sicuro. Finora non sono riuscito a farlo funzionare perché continuo a ricevere "Sorry, your nonce did not verify.".

Il codice completo è riportato di seguito, comprese le modifiche che ho apportato alle righe 42 e 103. Ecco anche un link al thread su pastebin, nel caso avessi bisogno di identificare le righe. In entrambe le righe ho cercato di seguire i suggerimenti da questa pagina di WordPress. Per favore, dai un'occhiata e fammi sapere perché il nonce continua a non verificarsi.

<?php
/*
Plugin Name: WPSE Crowded Cats
Plugin URI: https://wordpress.stackexchange.com/questions/43419/how-do-i-create-a-way-for-users-to-assign-categories-to-a-post-from-the-frontend
Description: Consente ai visitatori di modificare le categorie dei post. Pronto per l'uso con tassonomie personalizzate e tipi di post.
Version: 0.1
Author: WPSE
Author URI: https://wordpress.stackexchange.com/users/2110/maugly
License: GPL2
*/


add_action('plugins_loaded','wpse_init_crowd_cats_class');
function wpse_init_crowd_cats_class(){
    new WPSECrowdCatsClass();
}


class WPSECrowdCatsClass {

    function __construct() {

        // AGGIUNGI IL FORM AUTOMATICAMENTE AD OGNI POST
        add_filter( 'the_content', array( $this,'append_form' ) );

        // TAG DI AZIONE TEMPLATE DA USARE NEL TEMA
        // Uso: do_action('wpse_crowd_cats_form');
        // Uso: do_action('wpse_crowd_cats_form', $post_id, $taxonomy );
        add_action( 'wpse_crowd_cats_form', array( $this,'wpse_crowd_cats_form' ), 10, 2 );

        // ELABORAZIONE DEL FORM
        add_action( 'template_redirect', array( $this,'process_request' ) );

    }

    function process_request(){

        // verifica l'invio
        if ( ! isset($_POST['crowd-cat-radio']) || ! is_array($_POST['crowd-cat-radio']) )
            return;

        if ( !isset($_POST['nonce_name']) || !wp_verify_nonce($_POST['nonce_name'],'nonce_action') )
        {
            print 'Sorry, your nonce did not verify.';
            exit;
        } else {    // continua a elaborare i dati del form

            // sanifica e verifica l'input
            $suggested_terms = array_map( 'absint', $_POST['crowd-cat-radio'] );
            $post_id = absint( $_POST['crowd-cats-pid'] );
            $tax = $_POST['crowd-cats-tax'];
            if ( ! taxonomy_exists($tax) )
                return;

            // Consente solo termini esistenti. Non sono sicuro che sia necessario.
            $args = array( 'hide_empty' => false );
            $args = apply_filters( 'mcc_allowed_terms_args', $args, $post_id, $tax );
            $args['fields'] = 'ids';
            $allowed_terms = get_terms( $tax, $args );
            foreach ( $suggested_terms as $key => $term_id )
                if ( ! in_array( $term_id, $allowed_terms ) )
                    unset( $suggested_terms[$key] );

            // Aggiungi termini alla tassonomia
            $affected_terms = wp_set_object_terms( $post_id, $suggested_terms, $tax, false );
            update_term_cache($affected_terms);
            return $affected_terms;

        }
    }

    function get_form( $post_id=null, $tax='category' ) {

        if ( is_null($post_id) || ! taxonomy_exists($tax) )
            return false;

        $args = array( 'hide_empty' => false );
        $args = apply_filters( 'mcc_get_terms_args', $args, $post_id, $tax );
        $all_terms = get_terms( $tax, $args );

        if ( ! $all_terms )
            return false;

        $post_terms = wp_get_object_terms( $post_id, $tax, array( 'fields' => 'ids' ) );

        $permalink = get_permalink( $post_id );

        $out = "<form id='crowd-cats' action='$permalink' method='POST' >
           <ul >";

        foreach ( $all_terms as $t ) :

            $checked = in_array( $t->term_id, $post_terms) ? 'checked' : '';
            $out .= "<li>
                       <input type='checkbox' id='crowd-cat-$t->term_id' name='crowd-cat-radio[]' value='$t->term_id' $checked />
                       <label for='crowd-cat-$t->term_id' >".esc_attr($t->name)."</label>
                    </li>";

        endforeach;

        $out .= "</ul>
               <input type='submit' value='Submit' name='crowd-cats-submit'/>
               <input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/>
               <input type='hidden' value='".esc_attr($tax)."' name='crowd-cats-tax'/>
               <input type='hidden' value='$post_id' name='crowd-cats-pid'/>";

        //TODO: impostare nonce

        $out .= "</form>";

        return $out;

    }

    function append_form($content){

        global $post;

        if ( 'post' != $post->post_type )
            return $content;

        $form = $this->get_form( $post->ID );

        if ( ! $form )
            return $content;

        return "$content \n $form";
    }

    function wpse_crowd_cats_form( $post_id=null, $taxonomy='category' ) {

        if ( is_null($post_id) ) {
            global $post;
            $post_id = $post->ID;
        }

        echo $this->get_form( $post_id, $taxonomy );
    }

} // fine della classe              
?>

Sono abbastanza nuovo in PHP, per favore siate pazienti.

0
Tutte le risposte alla domanda 2
0

Non stai inserendo il campo nonce nel tuo form, quindi il tuo script non riceverà il campo nonce e questo codice:

 if ( !isset($_POST['nonce_name']))

Sarà validato perché $_POST['nonce_name'] non è impostato.

Nel tuo codice, rimuovi questa riga:

<input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/>

E, dove c'era scritto //TODO: set nonce, devi includere:

  $out .= wp_nonce_field( plugin_basename( __FILE__ ), 'nonce_name',true,false);

Nota: imposta il parametro 'echo' di wp_nonce_field() a false per recuperare il campo di input del nonce invece di stamparlo.

E poi verifica con:

if (!isset( $_POST['nonce_name'] ) || ! wp_verify_nonce( $_POST['nonce_name'], plugin_basename( __FILE__ ) ) )
        return;

Quindi, la tua function get_form() dovrebbe essere:

    function get_form( $post_id=null, $tax='category' ) {

        if ( is_null($post_id) || ! taxonomy_exists($tax) )
            return false;

        $args = array( 'hide_empty' => false );
        $args = apply_filters( 'mcc_get_terms_args', $args, $post_id, $tax );
        $all_terms = get_terms( $tax, $args );

        if ( ! $all_terms )
            return false;

        $post_terms = wp_get_object_terms( $post_id, $tax, array( 'fields' => 'ids' ) );

        $permalink = get_permalink( $post_id );

        $out = "<form id='crowd-cats' action='$permalink' method='POST' >
           <ul >";

        foreach ( $all_terms as $t ) :

            $checked = in_array( $t->term_id, $post_terms) ? 'checked' : '';
            $out .= "<li>
                       <input type='checkbox' id='crowd-cat-$t->term_id' name='crowd-cat-radio[]' value='$t->term_id' $checked />
                       <label for='crowd-cat-$t->term_id' >".esc_attr($t->name)."</label>
                    </li>";

        endforeach;

        $out .= "</ul>
               <input type='submit' value='Invia' name='crowd-cats-submit'/>
               <input type='hidden' value='".esc_attr($tax)."' name='crowd-cats-tax'/>
               <input type='hidden' value='$post_id' name='crowd-cats-pid'/>";

        $out .= wp_nonce_field( plugin_basename( __FILE__ ), 'nonce_name',true,false);

        $out .= "</form>";

        return $out;

    }

E la tua function process_request() dovrebbe essere:

    function process_request(){

        // verifica l'invio
        if ( ! isset($_POST['crowd-cat-radio']) || ! is_array($_POST['crowd-cat-radio']) )
            return;

if ( !isset($_POST['nonce_name']) || !wp_verify_nonce($_POST['nonce_name'],plugin_basename( __FILE__ )) )
      {
   print 'Spiacente, il tuo nonce non è stato verificato.';
   exit;
} else {    // continua a elaborare i dati del form

        // sanifica e verifica l'input
        $suggested_terms = array_map( 'absint', $_POST['crowd-cat-radio'] );
        $post_id = absint( $_POST['crowd-cats-pid'] );
        $tax = $_POST['crowd-cats-tax'];
        if ( ! taxonomy_exists($tax) )
            return;

        // Permetti solo termini esistenti. Non sono sicuro se sia necessario.
        $args = array( 'hide_empty' => false );
        $args = apply_filters( 'mcc_allowed_terms_args', $args, $post_id, $tax );
        $args['fields'] = 'ids';
        $allowed_terms = get_terms( $tax, $args );
        foreach ( $suggested_terms as $key => $term_id )
            if ( ! in_array( $term_id, $allowed_terms ) )
                unset( $suggested_terms[$key] );

        // Aggiungi termini alla tassonomia
        $affected_terms = wp_set_object_terms( $post_id, $suggested_terms, $tax, false );
        update_term_cache($affected_terms);
        return $affected_terms;

    }
}
11 set 2013 17:35:36
2

Penso che il tuo problema sia che hai <input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/> nel tuo codice, ma wp_nonce_field() genera già l'intero tag <input ...> per te. Dai un'occhiata al codice sorgente della tua pagina; probabilmente vedrai qualcosa del tipo:

<input type='hidden' value='<input type="hidden" value="abcdef1234">' />

Modifica il tuo $out in questo modo:

$out .= "</ul>
    <input type='submit' value='Invia' name='crowd-cats-submit'/>
    " . wp_nonce_field( 'action_name', 'nonce_name' ) . "
    <input type='hidden' value='".esc_attr($tax)."' name='crowd-cats-tax'/>
    <input type='hidden' value='$post_id' name='crowd-cats-pid'/>";
11 set 2013 17:38:10
Commenti

Uso Firebug e posso vedere il valore nel sorgente, ma per qualche motivo il valore, ad esempio 52f4D1ee4, rimane stabile ad ogni invio. Inoltre, le categorie non vengono impostate.

gurung gurung
11 set 2013 18:09:00

Il nonce viene generato solo ogni 12 (o forse 24) ore. Quindi ha senso che il valore del nonce rimanga lo stesso, a meno che non lo stai controllando a intervalli di un giorno.

Pat J Pat J
11 set 2013 21:41:42