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

新会话场景下基于客户端数据生成指纹时的wp_safe_redirect延迟执行问题求助

新会话场景下基于客户端数据生成指纹时的wp_safe_redirect延迟执行问题求助

我写了一个自定义脚本,会结合服务端和客户端数据生成指纹,用来阻止那些换不同IP反复访问的用户。我知道这不是100%可靠,但作为最后的安全机制,目前运行得还不错。

我遇到的问题是,当新会话首次加载页面时,PHP代码会比JavaScript收集客户端数据的操作先执行。具体来说,指纹函数被调用时,会话里还没有指纹,所以触发了generate_fingerprint(),但此时客户端数据还没通过POST传过来(因为JS还没运行),导致这个函数返回null,进而让阻塞机制在这个场景下失效。

以下是我用来生成基于客户端数据的指纹的代码(配合一个JavaScript文件):

function generate_advanced_fingerprint() {
    $components = [
        'screen_resolution' => $_POST['screen_resolution'] ?? '',
        'color_depth' => $_POST['color_depth'] ?? '',
        'canvas_fingerprint' => $_POST['canvas_fingerprint'] ?? '',
        'webgl_fingerprint' => $_POST['webgl_fingerprint'] ?? '',
        'audio_fingerprint' => $_POST['audio_fingerprint'] ?? '',
        'installed_fonts' => $_POST['installed_fonts'] ?? '',
        'hardware_concurrency' => $_POST['hardware_concurrency'] ?? '',
        'device_memory' => $_POST['device_memory'] ?? '',
        'browser_features' => $_POST['browser_features'] ?? ''
    ];

    if (in_array('', $components, true)) {
        return null;
    }
    ksort($components);
    $structured_data = json_encode($components);
    $fingerprint = md5($structured_data);
    return $fingerprint;
}

注:JavaScript是在<head>标签顶部执行的。

下面是我用来生成指纹并对比黑名单(一个JSON文件)进行阻塞检查的代码:

function handle_fingerprint() {
    if (!is_page('test')) {
        return;
    }

    $is_post_request = ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_FINGERPRINT_REQUEST']));

    if ($is_post_request) {
        // Process the POST data with client-side information
        $raw_post_data = file_get_contents('php://input');
        $json_data = json_decode($raw_post_data, true);
        if ($json_data) {
            $_POST = array_merge($_POST, $json_data);
        }
    }

    // Generate or retrieve the fingerprint
    if (!isset($_SESSION['fingerprint_generated']) || $is_post_request) {
        $fingerprint = generate_fingerprint();
        $_SESSION['fingerprint_generated'] = true;
        $_SESSION['current_fingerprint'] = $fingerprint;

        // Save the fingerprint if it is a POST request
        if ($is_post_request) {
            $ip = get_visitor_ip();
            save_fingerprint($ip, $fingerprint);
            
            // Send a response to the POST request
            header('Content-Type: application/json');
            echo json_encode(['success' => true]);
            exit;
        }
    } else {
        $fingerprint = $_SESSION['current_fingerprint'];
    }

    // Run the check
    $blocked_fingerprints = get_blocked_fingerprints();

    // Check fallback fingerprint
    if (in_array($fingerprint['fallback_fingerprint'], $blocked_fingerprints)) {
        wp_safe_redirect(home_url('/'));
        exit;
    }

    // Check advanced fingerprint
    if (isset($fingerprint['advanced_fingerprint']) && in_array($fingerprint['advanced_fingerprint'], $blocked_fingerprints)) {
        wp_safe_redirect(home_url('/'));
        exit;
    }

}

// Check the fingerprint on every pageload
add_action('wp', 'handle_fingerprint');

// Process POST requests for fingerprint data
add_action('init', function() {
    if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_SERVER['HTTP_X_FINGERPRINT_REQUEST'])) {
        handle_fingerprint();
    }
});

在新会话这个场景下,页面加载完成后,JavaScript会执行window.getFingerprint(),这个函数会收集客户端数据并通过POST请求发送到服务器,再次触发handle_fingerprint()。这时POST数据已经可用,generate_advanced_fingerprint()就能成功执行,生成完整的指纹。但这会导致两次调用(我可以通过错误日志看到)。

我试过只在所有数据都到位时才生成指纹:

if ($all_data_present) { 
    if (!isset($_SESSION['fingerprint_generated'])) {
        $fingerprint = generate_fingerprint();
        $_SESSION['fingerprint_generated'] = true;
        $_SESSION['current_fingerprint'] = $fingerprint;
    } else {
        $fingerprint = $_SESSION['current_fingerprint'];
    }

这个方法能生成指纹,但问题是当客户端数据到位时,页面内容已经输出了,wp_safe_redirect()的跳转机制就失效了。现在我想找一种方法,能延迟阻塞检查直到客户端数据可用,但至今还没成功。

另外还有两个要求:

  • 我不想显示错误消息,宁愿让用户跳转到一个“伪装”页面来迷惑他们,不让他们察觉到异常
  • 我也不想用JavaScript来做跳转,希望尽量使用wp_safe_redirect()这类服务端方法

有没有人能从新的角度帮我看看这个问题?

备注:内容来源于stack exchange,提问作者Flower88

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 16:53:01