wp_verify_nonce keeps failing

时间:2013-09-11 作者:gurung

我需要从前端分配要发布的类别,所以我正在使用该解决方案suggested in this thread , 以插件的形式。它正在按预期工作。我只是想添加一个nonce字段,以使其更加安全。到目前为止,我似乎还没能让它正常工作,因为我一直在说“对不起,你的暂时消息没有得到证实。”。

下面给出了完整的代码,包括我所做的更改,这些更改位于第42行和第103行。这里还有一个link to pastebin thread , 以防您需要识别线路。在这两行中,我都试图从this wordpress page .请看一看,让我知道为什么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: Allow visitors to change categories of posts. Ready to use with custom taxonomies and post types.
    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() {

            // APPEND THE FORM AUTOMATICALLY TO EVERY POST
            add_filter( \'the_content\', array( $this,\'append_form\' ) );

            // TEMPLATE ACTION TAG TO BE USED IN THEME
            // Usage: do_action(\'wpse_crowd_cats_form\');
            // Usage: do_action(\'wpse_crowd_cats_form\', $post_id, $taxonomy );
            add_action( \'wpse_crowd_cats_form\', array( $this,\'wpse_crowd_cats_form\' ), 10, 2 );

            // FORM PROCESSING
            add_action( \'template_redirect\', array( $this,\'process_request\' ) );

        }

        function process_request(){

            // check submission
            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 {    // continue to process form data

            // sanitize and check the 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;

            // Allow only existing terms. Not sure if this is needed.
            $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] );

            // Add terms to taxonomy
            $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: set 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 );
        }


    } // end of class              
    ?>
这里对php很陌生,请友好一点。

2 个回复
最合适的回答,由SO网友:cybmeta 整理而成

您没有在表单中插入nonce字段,因此脚本不会接收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);
注:设置wp_nonce_field() \'“echo”参数设置为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=\'Submit\' 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(){

        // check submission
        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 \'Sorry, your nonce did not verify.\';
   exit;
} else {    // continue to process form data

        // sanitize and check the 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;

        // Allow only existing terms. Not sure if this is needed.
        $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] );

        // Add terms to taxonomy
        $affected_terms = wp_set_object_terms( $post_id, $suggested_terms, $tax, false );
        update_term_cache($affected_terms);
        return $affected_terms;

    }
}

SO网友:Pat J

我想你的问题是<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=\'Submit\' 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\'/>";

结束

相关推荐

如何在前端提交表格中使用NONCE?

多亏了这里的各种帖子,我成功地整理了一份前端提交表单。经过大约24小时的调整,我终于让一切都正常了,包括提交后重定向到“成功”页面,但我不知道如何处理nonce。以下是表单页:http://pastebin.com/YWyXL3jY以下是成功页面:http://pastebin.com/3Usu0Pt6它们都是自定义页面模板(我知道目前格式有点乱,因为不同的部分来自不同的来源,我不想使用文件上传功能,因为我宁愿使用插件来提高安全性)。在将用户重定向到成功页面之前,是否需要处理nonce?我对nonce没有