wp_verify_nonce продолжает завершаться неудачей
Мне нужно было назначать категории записи с фронтенда, поэтому я использую решение, предложенное в этой ветке, в виде плагина. В целом всё работает как ожидается. Я просто хотел добавить поле nonce для повышения безопасности. Но пока что у меня не получается заставить его работать - постоянно получаю сообщение "Sorry, your nonce did not verify." ("Извините, ваш nonce не прошел проверку").
Ниже приведен полный код, включая мои изменения в строках 42 и 103. Также есть ссылка на pastebin, если вам нужно будет идентифицировать строки. В обоих случаях я пытался следовать подсказкам с этой страницы WordPress. Пожалуйста, посмотрите и подскажите, почему nonce не проходит проверку.
<?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: Позволяет посетителям изменять категории записей. Готов к использованию с пользовательскими таксономиями и типами записей.
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() {
// АВТОМАТИЧЕСКИ ДОБАВЛЯЕМ ФОРМУ К КАЖДОЙ ЗАПИСИ
add_filter( 'the_content', array( $this,'append_form' ) );
// ДЕЙСТВИЕ ДЛЯ ИСПОЛЬЗОВАНИЯ В ТЕМЕ
// Использование: do_action('wpse_crowd_cats_form');
// Использование: do_action('wpse_crowd_cats_form', $post_id, $taxonomy );
add_action( 'wpse_crowd_cats_form', array( $this,'wpse_crowd_cats_form' ), 10, 2 );
// ОБРАБОТКА ФОРМЫ
add_action( 'template_redirect', array( $this,'process_request' ) );
}
function process_request(){
// проверяем отправку формы
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 'Извините, ваш nonce не прошел проверку.';
exit;
} else { // продолжаем обработку данных формы
// очищаем и проверяем ввод
$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;
// Разрешаем только существующие термины. Не уверен, нужно ли это.
$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] );
// Добавляем термины в таксономию
$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='Отправить' 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: установить nonce
$out .= "</form>";
return $out;
}

Вы не добавляете поле nonce в свою форму, поэтому ваш скрипт не получит это поле, и данный код:
if ( !isset($_POST['nonce_name']))
Будет выполняться, так как $_POST['nonce_name']
не установлено.
В вашем коде удалите эту строку:
<input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/>
И там, где указано //TODO: set nonce
, вам нужно добавить:
$out .= wp_nonce_field( plugin_basename( __FILE__ ), 'nonce_name',true,false);
Примечание: установите параметр echo
функции wp_nonce_field()
в false, чтобы получить поле nonce, а не выводить его сразу.
А затем проверяйте с помощью:
if (!isset( $_POST['nonce_name'] ) || ! wp_verify_nonce( $_POST['nonce_name'], plugin_basename( __FILE__ ) ) )
return;
Таким образом, ваша function get_form()
должна выглядеть так:
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='Отправить' 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;
}
А ваша function process_request()
должна выглядеть так:
function process_request(){
// проверяем отправку формы
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 'Извините, ваша nonce-проверка не прошла.';
exit;
} else { // продолжаем обработку данных формы
// очищаем и проверяем ввод
$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;
// Разрешаем только существующие термины. Не уверен, нужно ли это.
$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] );
// Добавляем термины к таксономии
$affected_terms = wp_set_object_terms( $post_id, $suggested_terms, $tax, false );
update_term_cache($affected_terms);
return $affected_terms;
}
}

Я думаю, ваша проблема в том, что у вас есть <input type='hidden' value='".wp_nonce_field('nonce_action','nonce_name')."'/>
в коде, но функция wp_nonce_field()
уже генерирует весь тег <input ...>
за вас. Посмотрите исходный код вашей страницы; скорее всего, вы увидите что-то вроде:
<input type='hidden' value='<input type="hidden" value="abcdef1234">' />
Измените ваш $out
на что-то подобное:
$out .= "</ul>
<input type='submit' value='Отправить' 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'/>";

Я использую firebug и вижу значение в исходном коде, но по какой-то причине значение, например 52f4D1ee4, остается неизменным при каждой отправке. Также категории не устанавливаются.
