在AJAX调用中对Wordpress nonce进行故障排除

时间:2018-03-21 19:56:23

标签: php jquery ajax wordpress

我使用AJAX检查身体类并有条件地触发2个动作中的一个。如果支持Google语音API,则会加载支持语音搜索的表单。如果不是,则会加载常规搜索表单。

check_ajax_referer()函数即将发布403,因此我的nonce出现了问题。

该网站为mercury.photo。为简化起见,简化了代码;如果我不包含随机数检查,我已经知道它有效。

在我的剧本中,我有:

//-------------------------------------------------*/
// Speech Recognition
//-------------------------------------------------*/

jQuery(document).ready(function ($) {
  $(function () {
    // Add body class if browser supports Google Voice API
    if (Modernizr.speechrecognition) {
      $("body").addClass("voice-searchable");
    }
    var ajaxData;
    if ($("body").hasClass("voice-searchable")) {
      ajaxData = { "action": "my_voice" }
    } else {
      ajaxData = { "action": "my_novoice" }
    };
    xhr = new XMLHttpRequest();
    // Use a variable so we can callback 'done' and 'fail'; see https://medium.com/coding-design/writing-better-ajax-8ee4a7fb95f
    var ajaxCall = $.ajax({
      type: "POST",
      url: myVoiceSearch.ajaxurl,
      dataType: "html",
      data: ajaxData,
      security: myVoiceSearch.ajax_nonce
    });
    // 'success' & 'error' promises are deprecated; use 'done' and 'fail' instead
    ajaxCall.done(function (data) {
      $(".breadcrumb_search").html(data);
    });
    ajaxCall.fail(function (data, xhr, ajaxOptions, thrownError) {
      var errorMsg = "Oh, bother. Your AJAX request failed with a status code of " + xhr.responseText + ".";
      console.log( errorMsg );
    });
  });
});
(window, jQuery, window.Window_Ready);
// More scripts to load Google Voice API

functions.php中,我将我的脚本排入队列并添加操作:

/*
 * Ajax scripts for speech recognition
 */

add_action( 'wp_print_scripts', 'my_search_ajax_enqueue' );
function my_search_ajax_enqueue() {
  if ( ! is_admin() ) { // Load the script only on the front end
    $protocol = isset( $_SERVER['HTTPS'] ) ? 'https://' : 'http://';
    wp_register_script( "my-search-ajax-script", get_stylesheet_directory_uri() . '/js/speech-input.js', array( 'jquery' ) );

    $params = array( 'ajaxurl' => admin_url( 'admin-ajax.php', $protocol), 'ajax_nonce' => wp_create_nonce( 'my-create-voice-search-nonce' ), );

    wp_localize_script( 'my-search-ajax-script', 'myVoiceSearch', $params );

    wp_enqueue_script( 'my-search-ajax-script' );
  };
}

/**
 *
 * Generate custom search form
 *
 **/

function my_voice() {
  // This check fails
  check_ajax_referer( 'my-create-voice-search-nonce', 'security' );
  $form = 'A most excellent form, m’lord.';
  echo $form;
  wp_die();
}

add_action('wp_ajax_my_voice', 'my_voice');
add_action('wp_ajax_nopriv_my_voice', 'my_voice');

function my_novoice() {
  // check_ajax_referer( 'my-create-voice-search-nonce', 'security' );
  $form = 'Lame form, dude!';
  echo $form;
  wp_die();
}


add_action('wp_ajax_my_novoice', 'my_novoice');
add_action('wp_ajax_nopriv_my_novoice', 'my_novoice');
  1. 如何记录是否在AJAX调用中看到现时?
  2. 什么可能阻止nonce被设置(在我的PHP中)或收到(在我的AJAX中)?
  3. 编辑:做了一些阅读,看来WP nonces的主要功能是防止CSRF,因此,实际上只对登录用户有用。所以,还有更多问题:

    1. 我是否应该在这次AJAX通话中烦恼?
    2. 有没有更好的方法来处理验证通话的真实性?
    3. 编辑:进一步阅读证实我不应该这样做,因为它是一个前端形式。关闭这个问题,但如果你知道我的代码有什么问题,请随时评论/回答 - 我总是很高兴有机会学习!

      编辑:给出并接受答案。

1 个答案:

答案 0 :(得分:1)

wp_ajax回调函数可访问的所有变量都需要在jquery ajax请求的data参数中设置。因此,nonce值需要包含在ajaxData变量中,如下所示:

ajaxData = { "action": "my_voice", "security": myVoiceSearch.ajax_nonce}