说明

本文全篇围绕「Google reCAPTCHA v2 复选框」的前端使用进行说明,后端别忘了要验证哦;
由于 reCAPTCHA 在国内无法使用,请自行将域名替换为 https://www.recaptcha.net/

TL, DR

最终解决方案


官方 Example

Automatically render the reCAPTCHA widget

The easiest method for rendering the reCAPTCHA widget on your page is to include the necessary JavaScript resource and a g-recaptcha tag. The g-recaptcha tag is a DIV element with class name g-recaptcha and your site key in the data-sitekey attribute:

自动呈现 reCAPTCHA 小部件

在页面上呈现 reCAPTCHA 小部件的最简单方法是包括必要的 JavaScript 资源和 g-recaptcha 标记。g-recaptcha 标记是一个 DIV 元素,拥有名为 g-recaptcha 的 class 属性;并有一个 data-sitekey 属性,属性值为你的「网站密钥」:

<html>
  <head>
    <title>reCAPTCHA demo: Simple page</title>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" data-sitekey="your_site_key"></div>
      <br/>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

更人性化的 Example

但是这个 Example 其实并不好,为此我进行了亿些优化:

<html>
  <head>
    <title>reCAPTCHA demo: Great page</title>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" data-sitekey="your_site_key"></div>
      <!-- 「your_site_key」需替换为你的「网站密钥」 -->
      <br/>
      <input type="submit" value="Submit">
    </form>
    <script src="https://www.recaptcha.net/recaptcha/api.js" async defer></script>
    <!-- 听说放在下面有助于加快加载速度,想想不是没道理 -->
  </body>
</html>

这样一来,就可以在国内正常使用 reCAPTCHA 了。

你肯定要问:就这?

怎么可能 ==


动态加载 sitekey

在大项目里,特别是前后端分离的项目里,你是绝对不可能把 sitekey 写死的。因为你不可能为你的每一个用户都单独改 sitekey,用户们总希望主动权在他们手里。

对于 PHP 来说,这并不值得烦恼。可以将 sitekey 放入数据库,需要时在后端渲染完成,返回给客户端就行了。如果你使用 Django/Flask,他们都使用 Jinja2 作为模板引擎,也可以像 PHP 那样轻松搞定。

假设你的产品经理是个奇葩,他要求采用前后端分离的模式进行开发,你势必要用 Vue 来完成前端渲染。为了吃饭,你只好听他的。那么问题就来了,你该如何实现呢?

聪明机智的你试图用 v-bind:data-sitekey="siteKey" 的方式来完成数据绑定,从而让 reCAPTCHA 读取到信息。可事实证明这样不行,无论你怎么绑,这 reCAPTCHA 就是报错。

幸好,reCAPTCHA 提供了几个 Javascript API:

grecaptcha.render(
container,
parameters
)

Renders the container as a reCAPTCHA widget and returns the ID of the newly created widget.
container
The HTML element to render the reCAPTCHA widget. Specify either the ID of the container (string) or the DOM element itself.
parameters
An object containing parameters as key=value pairs, for example, {"sitekey": "your_site_key", "theme": "light"}.

将容器呈现为 reCAPTCHA 小部件,并返回新创建的小部件的 ID。
container
呈现 reCAPTCHA 小部件的 HTML 元素。指定容器的 ID(字符串)或 DOM 元素本身。
parameters
一个包含参数作为键值对的对象,例如{"sitekey": "your_site_key", "theme": "light"}

根据这个 API,可以写出以下代码:

HTML

<html>
  <head>
    <title>reCAPTCHA demo: Great page</title>
  </head>
  <body>
    <form action="?" method="POST">
      <div class="g-recaptcha" id="recaptcha"></div>
      <br/>
      <input type="submit" value="Submit">
    </form>
    <script src="https://www.recaptcha.net/recaptcha/api.js" async defer></script>
  </body>
</html>

Javascript

grecaptcha.render(
                'recaptcha',
                { "sitekey": secret }
            )

尝试过后,发现可以使用!但是,好景不长。

有时可以有时又报错。(营销号警告


大家都在聊的代码报错是什么梗?真相令人震惊!

你知道代码报错吗?代码报错最近为什么这么火?大家都知道,现代社会中随着人们生活水平的提高,代码报错如今也成为了人们茶余饭后的谈资。相信大家对代码报错都很熟悉,代码报错就是我们每天都会经常遇到的,但是代码报错是怎么回事呢?下面就让小编带大家一起了解一下代码报错是怎么回事吧。

代码报错其实就是代码报错,目前在网上拥有非常高的热度。大家可能会感到很惊讶,代码报错为什么是这样的?代码报错究竟为什么火起来了呢?但事实就是这样,小编也感到非常惊讶。

好了,以上就是代码报错是什么,代码报错为什么火的具体内容。欢迎大家在评论区和小编一起讨论,畅所欲言。


最终方案

原来,reCAPTCHA 的 JS 还没有加载完成,我们自己的 JS 就先调用它了,不报错才怪!那我该怎么办?难道要一直去检测 reCAPTCHA 有没有加载完成吗?

当然不需要,作为 Google 的开发者,他们留了一个 callback 给我们,叫 onload,作为 param 在加载 JS 的时候传入。在 reCAPTCHA 加载完毕后,会调用传入的函数。

例子:

<script src="https://www.recaptcha.net/recaptcha/api.js?onload=grecaptcha" async defer></script>

会调用 grecaptcha() 这个函数,而这个函数是我们预先写好的。

直接拿我的实际代码

function grecaptcha() {
    axios
        .get(`/api/recaptcha/getSiteKey`)
        .then(response => {
            grecaptcha.render(
                'recaptcha',  // 传入 ID 时不要 # 号
                { "sitekey": response.data };
            )
        })
        .catch(error => {
            console.log(error);
        });
}

通过 axios 向后端请求得到 sitekey

但我尝试一下还是不行,原因就是在于没有 render 参数!这个参数指定了是从 DIV 元素的 data-sitekey 中读取,还是用 JS 来渲染(显式加载)。
在这里我们需要显式加载,因此传入值为 explicit,代码就变成了这个样子:

<script src="https://www.recaptcha.net/recaptcha/api.js?onload=grecaptcha&render=explicit" async defer></script>

JS 不变,大功告成!


想要了解更多?那就去 Google Developers 吧!

By:XiaoJin-CC-BY-4.0