那个保存开关的接口,退出登录后用 curl 带一个 action 参数直接请求 admin-ajax.php,返回 success,后台选项真的被改了。整个过程不需要任何 Cookie。日志里能对上时间点,这种反而好排。

接口同时注册了未登录可访问的版本,回调里只判断参数有没有传,既没校验 nonce 也没查权限。未登录钩子本意是给前台读数据用的,拿来做写操作等于完全敞开。这一点先确认清楚,后面就不用反复试。

check_ajax_referer("abc_save_settings", "nonce");
if (!current_user_can("manage_options")) { wp_send_json_error(null, 403); }
// 只注册 wp_ajax_abc_save,不加 wp_ajax_nopriv_ 版本

「插件 ajax nonce 校验」确认了原因之后,改动尽量只碰那一处,顺手改的东西后面最容易出问题。偶发问题先统计频率,一小时几次和一天一次,查法完全不同。

改完顺手把文档补一句,省得下次自己重新推一遍。

处理上按这个顺序:写操作只注册登录版本 不要挂未登录的那一份;回调开头先校验 nonce 再查用户能力 两步都过才处理;前端请求把 nonce 一起带上 不要在页面里写死。

结果对不对很好判断,退出登录后重放同一条 curl 返回 403,后台选项值保持不变。

作者 9823189