这段时间在做 PHP 项目,需要用到验证码的功能。而谷歌的 reCaptcha 配置简单,我就弄了一个尝尝鲜。

准备

我们需要一个谷歌账户,去申请一个站点。成功后我们会得到 secretsitekey

前端配置

前端配置十分简单,只需要把官网提供的代码插入到任何一个 form 表单内即可。记得 sitekey 不要填写错了噢!

<div class="g-recaptcha" data-sitekey="你的 Key"></div>

然后增加一段 script 标签,官网提供的地址在国内因某些原因无法访问,这里提供一个替代地址。

<script src='https://recaptcha.net/recaptcha/api.js'></script>

这是我写的一段示例:

<h3>谷歌 GCaptcha 测试</h3>
<form method="post">
    <input name="username" placeholder="用户名"/>
    <div class="g-recaptcha" data-sitekey="你的 Key"></div>
    <button name="submit">提交</button>
</form>
<?php echo "<p>" . $msg . "</p>" ?>
<script src='https://recaptcha.net/recaptcha/api.js'></script>

你可能注意到上面出现了 PHP 和其 $msg 变量,这段主要用于展示后端的处理状态,即用户点击是否成功通过验证。

后端配置

简单来说,我们后端需要记录前端发送的一段 post 内容,并转发到谷歌的服务器。谷歌服务器将会返回验证结果给我们,如果成功的话就可以继续给用户服务啦!这是我在表白墙项目里编写的代码,在这经过一定的优化。

class Paul_GCaptcha {
    public static $success, $failed;

    // 发送验证信息
    public static function send($post_data) {
        $postdata = http_build_query($post_data);
        $options = array(
            'http' => array(
                'method' => 'POST',
                'header' => 'Content-type:application/x-www-form-urlencoded',
                'content' => $postdata,
                'timeout' => 15 * 60 // 超时时间
            )
        );
        $context = stream_context_create($options);  
        $result = file_get_contents("https://recaptcha.net/recaptcha/api/siteverify", false, $context);
        return $result;
    }

    // 判断验证状况
    public static function check(){
        if($_POST["g-recaptcha-response"]){
            $data = array(
                'secret' => '你的 Secret 密钥',
                'response' => $_POST["g-recaptcha-response"] // 接收用户提交的验证数据
            );

            $result = self::send($data);
            $result = json_decode($result, true);
            $result = $result["success"];

            if($result == true){
                return true; // 验证成功
            }
            else{
                return false; // 验证失败
            }
        }
        else{
            return false; // 用户没有提交到验证信息
        }
    }
}

修改上方 check 函数内的 secret 参数,在需要判断验证码的页面上运行该函数就可以啦!结合上方的 HTML,这样做就能实现最简单的判断啦!

// 如果提交了表单
if(isset($_POST["submit"])){

    // 返回 true 则成功通过验证
    if(Paul_GCaptcha::check() == true){
        $msg = "验证通过,欢迎你," . $_POST["username"] . "!";
    }
    else{
        $msg = "验证失败";
    }
}

体验优化

按照 官方文档 的服务端配置好之后发现一个问题,就是如果提交完表单,服务端才提示用户没有完成验证码,那用户体验就差很多了。

那么我们如何在表单未提交的时候判断用户是否完成验证呢?答案是,通过 reCaptcha 的这个 getResponse 方法,即可判断发送给服务器的表单内容。如果该值为空,则用户就没完成验证了。

grecaptcha.getResponse()

我们就可以在表单提交之前验证一下该方法返回的内容,趁早给用户提示信息,就可以提升交互体验。

HTML:

<form onsubmit="return check_grecaptcha()"></form>

JS:

function check_grecaptcha() {
    if(grecaptcha.getResponse() == ""){
        alert("请先进行人机验证");
        return false;
    }
    else{
        alert("验证通过");
        return true;
    }
}

参考来源:StackOverFlow