You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁止直接通过URL调用PHP,仅允许JavaScript触发游戏分数保存?

解决方案:禁止直接URL调用WordPress AJAX分数保存接口

要防止用户直接构造URL调用admin-ajax.php?action=save&score=100&user=Username,你需要从请求合法性验证入手,结合WordPress自带安全机制和前端请求规范实现,具体步骤如下:

1. 强制使用POST请求

直接URL调用默认是GET请求,你可以在save_score()函数里先判断请求方法,只处理POST请求:

function save_score() {
    // 只接受POST请求
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        wp_send_json_error(array('message' => '非法请求方式'), 403);
        wp_die();
    }

    // 处理分数参数
    $score = isset($_POST['score']) ? intval($_POST['score']) : 0;
    $user = isset($_POST['user']) ? sanitize_text_field($_POST['user']) : '';

    // 分数保存逻辑...
    
    wp_send_json_success(array('message' => '分数保存成功'));
    wp_die();
}
add_action('wp_ajax_save', 'save_score');
add_action('wp_ajax_nopriv_save', 'save_score'); // 允许未登录用户调用(按需开启)

同时修改前端JS,改用POST方式发送请求:

// 游戏完成后提交分数
function saveGameScore(score, username) {
    fetch('/wp-admin/admin-ajax.php', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
            action: 'save',
            score: score,
            user: username
        })
    })
    .then(response => response.json())
    .then(data => {
        data.success ? console.log('分数保存成功') : console.error('保存失败:', data.data.message);
    });
}

2. 添加WordPress Nonce验证(核心安全措施)

WordPress的Nonce(一次性随机数)能有效防止CSRF攻击和伪造请求,步骤如下:

步骤1:前端页面生成Nonce

通过页面输出或脚本本地化传递Nonce到前端:

// 方法1:在页面底部输出Nonce
function print_game_nonce() {
    $nonce = wp_create_nonce('game_score_save_nonce');
    echo "<script>const gameSaveNonce = '$nonce';</script>";
}
add_action('wp_footer', 'print_game_nonce');

// 方法2:通过wp_localize_script传递(适合注册过的JS脚本)
function enqueue_game_scripts() {
    wp_enqueue_script('game-script', get_template_directory_uri() . '/js/game.js', array('jquery'), '1.0', true);
    wp_localize_script('game-script', 'GameData', array(
        'ajax_url' => admin_url('admin-ajax.php'),
        'nonce' => wp_create_nonce('game_score_save_nonce')
    ));
}
add_action('wp_enqueue_scripts', 'enqueue_game_scripts');

步骤2:前端请求携带Nonce

修改JS请求,带上Nonce参数:

// 用wp_localize_script传递的情况
function saveGameScore(score, username) {
    fetch(GameData.ajax_url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: new URLSearchParams({
            action: 'save',
            score: score,
            user: username,
            _wpnonce: GameData.nonce // 携带Nonce
        })
    })
    .then(response => response.json())
    .then(data => {
        // 处理响应逻辑
    });
}

步骤3:后端验证Nonce

在save_score()函数开头添加Nonce验证:

function save_score() {
    // 验证请求方法
    if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
        wp_send_json_error(array('message' => '非法请求方式'), 403);
        wp_die();
    }

    // 验证Nonce有效性
    if (!isset($_POST['_wpnonce']) || !wp_verify_nonce($_POST['_wpnonce'], 'game_score_save_nonce')) {
        wp_send_json_error(array('message' => '请求验证失败'), 403);
        wp_die();
    }

    // 后续分数处理逻辑...
}

3. 补充:验证请求来源(可选增强)

可以检查请求Referer头,确保请求来自你的网站:

function save_score() {
    // ...前面的验证逻辑

    // 验证请求来源
    $allowed_referer = home_url();
    if (!isset($_SERVER['HTTP_REFERER']) || strpos($_SERVER['HTTP_REFERER'], $allowed_referer) === false) {
        wp_send_json_error(array('message' => '非法请求来源'), 403);
        wp_die();
    }

    // 后续逻辑...
}

注意:HTTP_REFERER可被篡改,仅作为补充验证,不能单独依赖。

4. 进阶:游戏会话状态验证

如果需要更高安全性,可以记录用户游戏会话:

  • 游戏开始时,前端请求生成一个会话ID,后端存储并标记为「进行中」
  • 游戏结束时,前端携带会话ID提交分数,后端验证会话ID存在且状态为「进行中」,验证通过后标记为「已完成」并保存分数

这种方式能彻底杜绝未游玩就提交分数的情况,但实现复杂度更高,适合对安全性要求极高的场景。


内容的提问来源于stack exchange,提问作者Darin H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:42:58