在WordPress中实施Cloudflare Turnstile

Cloudflare Turnstile 是一种现代的 CAPTCHA 替代方案,它不仅能够有效阻止机器人行为,还能提供更好的用户体验。

本文将介绍如何通过自定义WordPress插件实现 Cloudflare Turnstile 验证机制,并将其应用于登录页面和评论表单中。

Cloudflare Turnstile 是由 Cloudflare 提供的一项服务,用于识别用户是否为真实人类。与传统 CAPTCHA 不同的是,Turnstile 更加注重隐私保护和用户体验,支持无验证(Invisible)模式,能够在不影响用户操作的前提下完成验证。

class CloudflareTurnstile
{
    public function __construct(
        public string $site_key = '',
        public string $site_secret = ''
    ) {}

    /**
     * 调整登录界面样式
     */
    public function on_login_head()
    {
        ?>
            <style>
                #login { min-width: 350px; }
                #cf-turnstile { height: 80px; }
            </style>
        <?php
    }

    /**
     * 登录校验验证码
     */
    public function on_wp_authenticate_user($user)
    {
        if (!isset($_POST['cf-turnstile-response'])) {
            return $user;
        }

        $result = $this->verify($_POST['cf-turnstile-response']);
        if (is_wp_error($result)) {
            return $result;
        }

        return $user;
    }

    /**
     * 登录界面添加 Turnstile 验证码
     */
    public function on_login_form()
    {
        $disableLoginBtn = "document.getElementById('wp-submit').setAttribute('disabled', true)";
        $enableLoginBtn = "document.getElementById('wp-submit').removeAttribute('disabled')";
        $this->render_turnstile("() => {$enableLoginBtn}", $disableLoginBtn, 'login');
    }

    public function on_comment_form()
    {
        $disableCommentBtn = "document.getElementById('submit').setAttribute('disabled', true)";
        $enableCommentBtn = "document.getElementById('submit').removeAttribute('disabled')";
        $this->render_turnstile("() => {$enableCommentBtn}", $disableCommentBtn, 'comment');
    }

    /**
     * 获取用户IP地址
     */
    private function get_user_ip() {
        $ip = $_SERVER['REMOTE_ADDR'];

        if (!empty($_SERVER['HTTP_CLIENT_IP'] ?? null)) {
            $ip = $_SERVER['HTTP_CLIENT_IP'];
        }

        if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'] ?? null)) {
            $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        }

        return apply_filters('get_user_ip', $ip);
    }

    /**
     * 校验响应码
     */
    private function verify($turnstile_response)
    {
        $response = wp_remote_post('https://challenges.cloudflare.com/turnstile/v0/siteverify', [
            'headers' => [
                'content-type' => 'application/json'
            ],
            'body' => json_encode([
                'secret' => $this->site_secret,
                'response' => $turnstile_response,
                'remoteip' => $this->get_user_ip()
            ])
        ]);

        $data = wp_remote_retrieve_body($response);
        if (empty($data)) {
            return new \WP_Error('turnstile_error', 'Turnstile 验证失败!');
        }

        $data = json_decode($data, true);
        if ($data == false || $data == null) {
            return new \WP_Error('turnstile_error', '无法解析 Turnstile 响应数据!');
        }

        if (!isset($data['success'])) {
            return new \WP_Error('turnstile_error', 'Turnstile 返回异常!');
        }

        if ($data['success'] !== true) {
            return new \WP_Error(
                $data['error-codes'][0] ?? 'turnstile_error',
                $data['message'] ?? 'Turnstile 验证未通过'
            );
        }

        return true;
    }

    /**
     * 渲染 Turnstile 验证码
     */
    private function render_turnstile(
        $js_callback = '',
        $page_load_script = '',
        $action = '',
        $id = 'cf-turnstile'
    ) {
        wp_enqueue_script(
            'ianzhi-seo-cloudflare-turnstile',
            'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit',
            [],
            null
        );
        ?>
            <div id="<?php echo esc_attr($id); ?>"></div>
            <script>
                window.onload = function () {
                    <?php echo esc_js($page_load_script); ?>

                    turnstile.ready(function () {
                        turnstile.render("#<?php echo esc_attr($id); ?>", {
                            sitekey: "<?php echo esc_attr($this->site_key); ?>",
                            action: '<?php echo esc_attr($action); ?>',
                            callback: <?php echo esc_js($js_callback); ?>
                        });
                    });
                }
            </script>
        <?php
    }
}

// 实例化插件并绑定到 WordPress 钩子
$cft = new CloudflareTurnstile('你的SITE_KEY', '你的SECRET_KEY');
add_action('login_head', [$cft, 'on_login_head']);
add_action('login_form', [$cft, 'on_login_form']);
add_filter('wp_authenticate_user', [$cft, 'on_wp_authenticate_user'], 10, 1);

// 如果需要启用评论表单验证,请取消注释下一行
// add_action('comment_form_before', [$cft, 'on_comment_form']);

通过本篇文章,你已经掌握了如何在 WordPress 中以面向对象的方式集成 Cloudflare Turnstile 验证系统,并将其应用到登录和评论流程中。这种做法不仅能提升网站的安全性,同时也能为用户提供更流畅的操作体验。

如果你正在寻找替代传统 CAPTCHA 的现代化解决方案,Cloudflare Turnstile 是一个非常值得尝试的选择。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注