Google reCAPTCHA:如何在服务器端获取用户响应和验证

时间:2014-12-04 14:55:37

标签: java javascript recaptcha

我正在做一个Java(JSP + Servlet)Web应用程序(我知道这个问题与技术无关)。我希望使用最新的Goolge reCAPTCHA服务。

我正在玩这里的Goolge reCAPTCHA示例:

https://developers.google.com/recaptcha/docs/display#config

<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="my_site_key"></div>
      <br/>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

我能够看到显示的重拍图像如下:

enter image description here

当我检查&#34;我不是机器人&#34;时,我得到以下内容:

enter image description here

如您所见,有一个验证按钮,根据我的测试,用户响应会发送给Google进行验证。

如何获取用户响应,以便我可以在自己的后端代码中验证用户响应(正如Google https://developers.google.com/recaptcha/docs/verify所建议的那样)。

g-recaptcha-response POST parameter when the user submits the form on your site

在服务器端,我可以通过点击&#34;提交&#34;按钮,从参数&#34; g-recaptcha-response&#34;获取用户输入仅在首先使用Google成功验证用户时。否则,&#34; g-recaptcha-response&#34;在服务器端是空白的。这意味着只有在客户端验证成功后才能进行服务器端验证。如果是这样,那么在服务器端进行另一次验证是什么意思,这是Google reCAPTHA提供的选项?

我错过了什么吗?

4 个答案:

答案 0 :(得分:73)

新版Google Recaptcha的一个很酷的事情是验证现在完全封装在小部件中。这意味着,小部件将负责提出问题,一直验证响应,直到确定用户实际上是人,然后才能获得 g-recaptcha-response 值。

但这并不能保证您的网站免受HTTP客户端请求伪造。

任何具有HTTP POST知识的人都可以将随机数据放在 g-recaptcha-response 表单字段中,然后在您的网站上使其认为该字段是由google小部件提供的。所以你来验证这个令牌。

在人类演讲中,它就像是,

  • 你的服务器:嘿谷歌,有一个家伙告诉我他不是机器人。他说你已经证实他是一个人,他告诉我给你这个标记作为证明。
  • Google :嗯...让我检查这个令牌......是的我记得这个家伙我给了他这个令牌......是的,他是用肉做的骨让他通过。
  • 你的服务器:嘿谷歌,还有另一个家伙告诉我他是一个人。他还给了我一个代币。
  • Google :嗯......这和你上次给我的一样......我很确定这个家伙正试图欺骗你。告诉他离开你的网站。

验证响应非常简单。只需向GET请求

https://www.google.com/recaptcha/api/siteverify?secret=your_secret&response=response_string&remoteip=user_ip_address

response_string 替换为您之前通过 g-recaptcha-response 字段获得的值。

您将获得带有成功字段的JSON响应。

此处提供更多信息: https://developers.google.com/recaptcha/docs/verify

答案 1 :(得分:9)

我在登录servlet中使用的方法来验证reCaptcha响应。使用java.json包中的类。返回JsonObject中的API响应。

检查成功字段是否为真或

private JsonObject validateCaptcha(String secret, String response, String remoteip)
{
    JsonObject jsonObject = null;
    URLConnection connection = null;
    InputStream is = null;
    String charset = java.nio.charset.StandardCharsets.UTF_8.name();

    String url = "https://www.google.com/recaptcha/api/siteverify";
    try {            
        String query = String.format("secret=%s&response=%s&remoteip=%s", 
        URLEncoder.encode(secret, charset), 
        URLEncoder.encode(response, charset),
        URLEncoder.encode(remoteip, charset));

        connection = new URL(url + "?" + query).openConnection();
        is = connection.getInputStream();
        JsonReader rdr = Json.createReader(is);
        jsonObject = rdr.readObject();

    } catch (IOException ex) {
        Logger.getLogger(Login.class.getName()).log(Level.SEVERE, null, ex);
    }
    finally {
        if (is != null) {
            try {
                is.close();
            } catch (IOException e) {
            }

        }
    }
    return jsonObject;
}

答案 2 :(得分:3)

您好奇,您可以在客户端验证您的google recaptcha 100%工作让我验证您的google recaptcha,请参阅下面的代码
这个代码在html正文:

 <div class="g-recaptcha" id="rcaptcha" style="margin-left: 90px;" data-sitekey="my_key"></div>
 <span id="captcha" style="margin-left:100px;color:red" />

此代码放在电话get_action(this)方法表单按钮的主题部分:

function get_action(form) {

var v = grecaptcha.getResponse();
if(v.length == 0)
{
    document.getElementById('captcha').innerHTML="You can't leave Captcha Code empty";
    return false;
}
 if(v.length != 0)
 {
    document.getElementById('captcha').innerHTML="Captcha completed";
    return true; 
 }
}

答案 3 :(得分:0)

这里是完整的演示代码,以了解客户端和服务器端的过程。您可以复制粘贴它,而只需替换 google site key google secret key。

<?php 
if(!empty($_REQUEST))
{
      //  echo '<pre>'; print_r($_REQUEST); die('END');
        $post = [
            'secret' => 'Your Secret key',
            'response' => $_REQUEST['g-recaptcha-response'],
        ];
        $ch = curl_init();

        curl_setopt($ch, CURLOPT_URL,"https://www.google.com/recaptcha/api/siteverify");
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $server_output = curl_exec($ch);

        curl_close ($ch);
        echo '<pre>'; print_r($server_output); die('ss');
}
?>
<html>
  <head>
    <title>reCAPTCHA demo: Explicit render for multiple widgets</title>
    <script type="text/javascript">
      var site_key = 'Your Site key';
      var verifyCallback = function(response) {
        alert(response);
      };
      var widgetId1;
      var widgetId2;
      var onloadCallback = function() {
        // Renders the HTML element with id 'example1' as a reCAPTCHA widget.
        // The id of the reCAPTCHA widget is assigned to 'widgetId1'.
        widgetId1 = grecaptcha.render('example1', {
          'sitekey' : site_key,
          'theme' : 'light'
        });
        widgetId2 = grecaptcha.render(document.getElementById('example2'), {
          'sitekey' : site_key
        });
        grecaptcha.render('example3', {
          'sitekey' : site_key,
          'callback' : verifyCallback,
          'theme' : 'dark'
        });
      };
    </script>
  </head>
  <body>
    <!-- The g-recaptcha-response string displays in an alert message upon submit. -->
    <form action="javascript:alert(grecaptcha.getResponse(widgetId1));">
      <div id="example1"></div>
      <br>
      <input type="submit" value="getResponse">
    </form>
    <br>
    <!-- Resets reCAPTCHA widgetId2 upon submit. -->
    <form action="javascript:grecaptcha.reset(widgetId2);">
      <div id="example2"></div>
      <br>
      <input type="submit" value="reset">
    </form>
    <br>
    <!-- POSTs back to the page's URL upon submit with a g-recaptcha-response POST parameter. -->
    <form action="?" method="POST">
      <div id="example3"></div>
      <br>
      <input type="submit" value="Submit">
    </form>
    <script src="https://www.google.com/recaptcha/api.js?onload=onloadCallback&render=explicit"
        async defer>
    </script>
  </body>
</html>