You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

reCaptcha V2邮件发送验证问题及表单错误提示优化需求

解决你的表单验证问题:reCaptcha失效与前端错误提示

咱们先聚焦你最关心的reCaptcha问题——不管勾不勾选都能提交表单,这大概率是后端没做真正的验证逻辑,或者前端没正确传递验证令牌导致的。下面一步步帮你修复:

一、搞定reCaptcha验证失效的问题

1. 先确保前端表单正确集成reCaptcha

首先得在表单里放上reCaptcha的组件,这样用户操作后才会生成验证令牌。把这段代码加到你的表单里(记得替换成自己的site key):

<form method="POST" action="你的表单处理脚本.php">
  <!-- 你的其他表单字段,比如输入框、按钮 -->
  <div class="g-recaptcha" data-sitekey="你的Site Key"></div>
  <button type="submit">提交</button>
</form>
<script src="https://www.google.com/recaptcha/api.js" async defer></script>

用户勾选reCaptcha后,这个组件会自动生成一个g-recaptcha-response字段,表单提交时会一起发给后端,这是验证的关键。

2. 完善后端的验证逻辑

你提供的post_captcha函数看起来不完整,咱们把它补全,确保能正确调用Google的验证接口,并且严格检查结果:

function post_captcha($user_response) {
    $secret_key = "你的Secret Key"; // 这里换成你自己的密钥
    $verify_url = 'https://www.google.com/recaptcha/api/siteverify';
    
    // 准备要发送的验证数据,包含密钥、用户响应和用户IP
    $data = [
        'secret' => $secret_key,
        'response' => $user_response,
        'remoteip' => $_SERVER['REMOTE_ADDR']
    ];

    // 设置HTTP请求选项
    $options = [
        'http' => [
            'header'  => "Content-type: application/x-www-form-urlencoded\r\n",
            'method'  => 'POST',
            'content' => http_build_query($data)
        ]
    ];

    $context = stream_context_create($options);
    $result = file_get_contents($verify_url, false, $context);
    // 把返回的JSON转成数组,方便判断结果
    return json_decode($result, true);
}

// 表单处理逻辑里必须加验证步骤
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    // 获取用户的reCaptcha响应令牌,如果用户没勾选,这个值是空的
    $captcha_response = $_POST['g-recaptcha-response'] ?? '';
    
    // 调用验证函数
    $captcha_result = post_captcha($captcha_response);
    
    // 重点!只有验证成功(success为true),才允许处理表单
    if (!$captcha_result['success']) {
        // 验证失败,这里可以存个错误信息,后面显示给用户
        $error_messages[] = '请完成reCaptcha验证才能提交!';
        // 直接阻止后续的表单处理逻辑
    } else {
        // 验证通过,这里写你的表单提交逻辑,比如存数据库、发邮件等
        // ...
    }
}

这里要注意几个关键点:

  • 一定要检查$captcha_result['success']的值,只有它为true时,才说明用户通过了reCaptcha验证
  • Secret Key和前端的Site Key必须是同一个reCaptcha项目里的,配对错了肯定验证失败
  • 加上remoteip参数(用户的IP地址)是Google推荐的,能提升验证的安全性,避免恶意请求

3. 排查常见坑

如果还是不行,你可以试试这几个排查步骤:

  • var_dump($_POST)打印提交的参数,看看有没有g-recaptcha-response这个字段,要是没有,说明前端的reCaptcha组件没加载好
  • 检查你的密钥是否正确,去Google reCaptcha后台确认Site Key和Secret Key的类型(v2还是v3)和项目匹配
  • 测试服务器能不能访问Google的验证接口,要是服务器连不上https://www.google.com/recaptcha/api/siteverify,验证肯定失败,可以用curl命令测试一下

二、实现前端文本字段的错误提示

这个需求也简单,咱们可以在后端收集所有错误,然后在当前页面对应字段下面显示:

1. 后端收集错误信息

在表单处理逻辑里,加上字段验证,把错误存到数组里:

$error_messages = [];

// 举个例子,验证邮箱字段
if (empty($_POST['email']) || !filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
    $error_messages['email'] = '请输入有效的邮箱地址!';
}

// 验证其他字段,比如用户名不能为空
if (empty($_POST['username'])) {
    $error_messages['username'] = '用户名不能为空!';
}

// 别忘了reCaptcha的错误
if (!$captcha_result['success']) {
    $error_messages['captcha'] = '请完成reCaptcha验证!';
}

// 只有当没有错误的时候,才处理表单提交
if (empty($error_messages)) {
    // 处理表单逻辑
}

2. 前端显示错误

在表单对应的字段旁边,加上错误信息的占位,用PHP判断有没有错误,有的话就显示:

<form method="POST" action="你的表单处理脚本.php">
    <div>
        <label for="email">邮箱:</label>
        <input type="email" name="email" id="email" value="<?php echo $_POST['email'] ?? ''; ?>">
        <!-- 显示邮箱的错误信息 -->
        <?php if (isset($error_messages['email'])): ?>
            <p style="color: red;"><?php echo $error_messages['email']; ?></p>
        <?php endif; ?>
    </div>

    <div>
        <label for="username">用户名:</label>
        <input type="text" name="username" id="username" value="<?php echo $_POST['username'] ?? ''; ?>">
        <?php if (isset($error_messages['username'])): ?>
            <p style="color: red;"><?php echo $error_messages['username']; ?></p>
        <?php endif; ?>
    </div>

    <div class="g-recaptcha" data-sitekey="你的Site Key"></div>
    <?php if (isset($error_messages['captcha'])): ?>
        <p style="color: red;"><?php echo $error_messages['captcha']; ?></p>
    <?php endif; ?>

    <button type="submit">提交</button>
</form>

这样用户提交无效内容时,错误信息会直接显示在对应字段下面,不用跳转页面,体验也更好。

内容的提问来源于stack exchange,提问作者Stephen Campbell

火山引擎 最新活动