WordPress Ajax调用报400(Bad Request)错误求助
问题背景
在WordPress环境中,指定页面(ID2614、2654)加载的JavaScript发起Ajax调用返回400(Bad Request),PHP处理函数AjaxSessionIDerzeugen完全未触发。已确认JS和PHP文件加载正常,Ajax URL正确,action参数配置无误,但钩子未生效。
1. 页面判断逻辑错误(functions.php)
原代码中页面判断使用了赋值运算符=而非比较运算符==,导致无论当前页面ID是什么,条件都会强制为真,可能引发不必要的代码加载冲突,甚至干扰其他页面的AJAX逻辑。
修复代码:
function LoadScriptsOnSpecificPages(){ global $wp_query; $page_id = intval($wp_query->queried_object->ID); // Page ID 2614 = Buchung Auswahl Raum, Page ID 2654 = Buchung abschließen if (($page_id == 2614) || ($page_id == 2654)) { include get_stylesheet_directory() . '/custom/booking.php'; // 修改脚本ID为唯一标识,避免与通用名称冲突 wp_enqueue_script( 'booking-script', get_stylesheet_directory_uri() . '/custom/booking.js', array( 'jquery' ), 1.1, true); } } add_action('template_redirect', 'LoadScriptsOnSpecificPages');
2. AJAX钩子注册时机过晚(booking.php)
在template_redirect钩子中才引入booking.php,而wp_ajax_*系列钩子需要在init或更早的阶段完成注册,才能被WordPress的AJAX机制识别。当前注册时机延迟,导致钩子未被正确挂载。
修复方案:
将booking.php的引入移到functions.php的顶部(或after_setup_theme钩子中),确保钩子在WordPress初始化流程早期完成注册;或者直接把钩子注册代码迁移到functions.php中,避免延迟加载导致的钩子失效。
3. SQL语法错误(AjaxSessionIDerzeugen函数)
原SQL语句存在明显语法错误,即使函数被触发,也会因SQL执行失败导致异常,且当前代码未处理错误反馈。同时未使用WordPress内置的防注入机制,存在安全风险。
修复代码:
// Ajax Session ID erzeugen function AjaxSessionIDerzeugen() { global $wpdb; // 验证nonce(后续步骤添加) if (!wp_verify_nonce($_POST['nonce'], 'booking_session_nonce')) { wp_send_json_error(array('message' => '无效的安全令牌')); } // 校验请求合法性 if ( isset($_POST['action']) && $_POST['action'] === 'AjaxSessionIDerzeugen' ) { // 结合IP增强session_id唯一性 $session_id = substr(md5(time() . $_SERVER["REMOTE_ADDR"]), 0, 10); // 使用$wpdb->prepare防止SQL注入,修复INSERT语法 $strsql = $wpdb->prepare("INSERT INTO tbl_buchungen (session_id) VALUES (%s)", $session_id); $result = $wpdb->query($strsql); $arr = array(); if ($result !== false) { $arr['pruefergebnis'] = "ok"; $arr['session_id'] = $session_id; } else { $arr['pruefergebnis'] = "error"; $arr['message'] = $wpdb->last_error; } // WordPress内置JSON输出函数,自动处理header和终止程序 wp_send_json($arr); } wp_send_json_error(array('message' => '无效请求')); }
4. 缺少CSRF安全验证(WordPress强制要求)
WordPress默认对未登录用户的AJAX请求要求CSRF令牌(nonce),缺少令牌会直接触发400错误,这是最常见的导致AJAX 400的原因。
修复步骤:
- 在PHP中添加nonce到脚本本地化数据(替代原
define_ajax_url函数):
function booking_enqueue_scripts() { wp_localize_script( 'booking-script', 'bookingAjax', array( 'ajaxurl' => admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('booking_session_nonce') ) ); } add_action('wp_enqueue_scripts', 'booking_enqueue_scripts');
- 修改JS中的AJAX请求:
if ((session_id == '') || (session_id == null)) { $.ajax({ url: bookingAjax.ajaxurl, type: 'POST', // 指定POST方法,符合WordPress AJAX规范 data: { 'action':'AjaxSessionIDerzeugen', 'nonce': bookingAjax.nonce // 携带安全令牌 }, success:function(antwort) { pruefergebnis = antwort.pruefergebnis; if (pruefergebnis == 'ok') { session_id = antwort.session_id; // 修正cookie过期时间格式,max-age更直观 document.cookie = "session_id=" + session_id + "; max-age=3600; path=/"; } else { window.alert(antwort.message || pruefergebnis); } }, error: function(xhr, status, error){ window.alert('请求错误: ' + error); } }); }
5. 无效代码干扰(AjaxSessionIDerzeugen函数)
原函数中存在无意义的callback:标签,虽然不会直接导致400错误,但属于无效代码,可能引发解析问题,建议直接移除。
内容的提问来源于stack exchange,提问作者Jörg

