wp_verify_nonce продолжает завершаться неудачей

11 сент. 2013 г., 17:09:59
Просмотры: 14.1K
Голосов: 0

Мне нужно было назначать категории записи с фронтенда, поэтому я использую решение, предложенное в этой ветке, в виде плагина. В целом всё работает как ожидается. Я просто хотел добавить поле 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;

        }
0
Все ответы на вопрос 2
0

Вы не добавляете поле 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;

    }
}
11 сент. 2013 г. 17:35:36
2

Я думаю, ваша проблема в том, что у вас есть <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'/>";
11 сент. 2013 г. 17:38:10
Комментарии

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

gurung gurung
11 сент. 2013 г. 18:09:00

Nonce будет генерироваться только каждые 12 (или 24) часов. Поэтому логично, что значение nonce остается одинаковым, если только вы не проверяете его с интервалами в целый день.

Pat J Pat J
11 сент. 2013 г. 21:41:42