wp_verify_nonce returnează eroare - Soluții și explicații
Am avut nevoie să atribui categorii postărilor din frontend, așa că am folosit soluția sugerată în acest thread, sub forma unui plugin. Funcționează conform așteptărilor. Am vrut să adaug un câmp nonce pentru a o face puțin mai sigură. Până acum nu am reușit să o fac să funcționeze, deoarece primesc constant mesajul "Ne pare rău, nonce-ul dumneavoastră nu s-a verificat.".
Codul complet este dat mai jos, inclusiv modificările pe care le-am făcut, care se află pe liniile 42 și 103. Aici este și un link către thread-ul de pe pastebin, în caz că aveți nevoie să identificați liniile. Pe ambele linii am încercat să iau indicii din această pagină WordPress. Vă rog să aruncați o privire și să-mi spuneți de ce nonce-ul continuă să eșueze la verificare.
<?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: Permite vizitatorilor să schimbe categoriile postărilor. Gata de utilizat cu taxonomii și tipuri de postări personalizate.
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() {
// ADAUGĂ AUTOMAT FORMULARUL LA FIECARE POSTARE
add_filter( 'the_content', array( $this,'append_form' ) );
// ETICHETĂ DE ACȚIUNE PENTRU ȘABLON DE UTILIZAT ÎN TEMĂ
// Utilizare: do_action('wpse_crowd_cats_form');
// Utilizare: do_action('wpse_crowd_cats_form', $post_id, $taxonomy );
add_action( 'wpse_crowd_cats_form', array( $this,'wpse_crowd_cats_form' ), 10, 2 );
// PROCESAREA FORMULARULUI
add_action( 'template_redirect', array( $this,'process_request' ) );
}
function process_request(){
// verifică trimiterea
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 'Ne pare rău, nonce-ul dumneavoastră nu s-a verificat.';
exit;
} else { // continuă procesarea datelor formularului
// sanitizează și verifică inputul
$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;
// Permite doar termeni existenti. Nu sunt sigur dacă este necesar.
$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] );
// Adaugă termeni la taxonomie
$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='Trimite' 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: setează nonce
$out .= "</form>";
return $out;
}

Nu includeți câmpul nonce în formularul tău, așa că scriptul tău nu va primi câmpul nonce și acest cod:
if ( !isset($_POST['nonce_name']))
Va fi validat deoarece $_POST['nonce_name']
nu este setat.
În codul tău, elimină această linie:
<input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/>
Și, unde scrie //TODO: set nonce
, trebuie să incluzi:
$out .= wp_nonce_field( plugin_basename( __FILE__ ), 'nonce_name',true,false);
Notă: setează parametrul 'echo' al wp_nonce_field()
la false pentru a prelua câmpul de input nonce în loc să-l afișeze.
Și apoi verifică prin:
if (!isset( $_POST['nonce_name'] ) || ! wp_verify_nonce( $_POST['nonce_name'], plugin_basename( __FILE__ ) ) )
return;
Deci, funcția ta function get_form()
ar trebui să fie:
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='Trimite' 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;
}
Și funcția ta function process_request()
ar trebui să fie:
function process_request(){
// verifică trimiterea
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 'Ne pare rău, nonce-ul tău nu s-a verificat.';
exit;
} else { // continuă procesarea datelor formularului
// sanitizează și verifică inputul
$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;
// Permite doar termeni existenți. Nu sunt sigur dacă este necesar.
$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] );
// Adaugă termeni la taxonomie
$affected_terms = wp_set_object_terms( $post_id, $suggested_terms, $tax, false );
update_term_cache($affected_terms);
return $affected_terms;
}
}

Cred că problema ta este că ai <input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/>
în codul tău, dar wp_nonce_field()
generează întregul <input ...>
pentru tine. Uită-te în sursa paginii tale; probabil vei vedea ceva de genul:
<input type='hidden' value='<input type="hidden" value="abcdef1234">' />
Schimbă $out
cu ceva de genul acesta:
$out .= "</ul>
<input type='submit' value='Trimite' 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'/>";

Folosesc Firebug și pot vedea valoarea în sursă, dar din anumite motive valoarea de ex. 52f4D1ee4 rămâne stabilă la fiecare trimitere. De asemenea, categoriile nu sunt setate.
