如何在程序中处理reCAPTCHA

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在程序中处理reCAPTCHA相关的知识,希望对你有一定的参考价值。

本文不是讲如何破解谷歌的reCAPTCHA(实际上我们也办不到),而是介绍在程序中借助第三方(人工)打码平台顺利通过reCAPTCHA验证。
由于使用人工打码会产生费用,并且费用是和调用次数成正比的,所以本方法仅适用于reCAPTCHA出现频率比较低的场景,例如:
1)网站登录使用了reCAPTCHA。比如,有时Linkedin登录就会出现reCAPTCHA(如下图所示),验证当前客户端是否是“真人”。

2)网站对访问频率过快的客户端返回reCAPTCHA,通过验证后即可继续访问。比如Zocdoc.com这个网站。

下面进入正题。如何在程序中借助第三方(人工)打码平台通过reCAPTCHA验证?
因为reCAPTCHA表单是JS动态创建的,我们遇到的第一个难题就是如何获取到reCAPTCHA表单中的验证码图片的路径及各隐藏表单域的值。
1)一个办法就是使用类似webkit的浏览器模拟工具(例如,phantomjs)加载页面,这样就能直接获取到JS生成的html源码。但是实现起来比较复杂,还需要借助第三方的软件。
2)查看源码会发现如果页面禁用了JS,reCAPTCHA将使用iframe模式加载(如下示),此时验证码图片路径和各表单项都是直接可见的。
这个问题解决了。接下来我们要获取到验证码图片对应的明文。如何调用第三方打码平台进行图片验证码识别呢?
我们需要先下载验证码图片,再把图片的二进制数据上传给打码平台,然后等待平台人工打码返回明文。打码平台一般都提供了供各种常见语言调用的API,所以该过程也比较简单。
现在我们已经获取到验证码图片对应的明文,只要我们将其和其它隐藏表单域参数一起提交就能完成验证过程了。

闲话不多说,还是直接上代码比较实在(Python实现, 这是我们真实项目中用到的):
view plaincopy to clipboardprint?
# coding: utf-8
# recaptcha.py

import sys
import os
os.chdir(os.path.dirname(os.path.realpath(sys.argv[0])))
import re
import StringIO
import deathbycaptcha
from urlparse import urljoin
from webscraping import common, xpath

DEATHBYCAPTCHA_USERNAME = '******'
DEATHBYCAPTCHA_PASSWORD = '******'

def read_captcha(image):
"""image - fileobj, the captcha to be recognized
"""
client = deathbycaptcha.SocketClient(DEATHBYCAPTCHA_USERNAME, DEATHBYCAPTCHA_PASSWORD)
try:
balance = client.get_balance()
# Put your CAPTCHA file name or file-like object, and optional
# solving timeout (in seconds) here:
common.logger.info('Submit captcha to http://deathbycaptcha.com/.')
captcha = client.decode(image)
if captcha:
# The CAPTCHA was solved; captcha["captcha"] item holds its
# numeric ID, and captcha["text"] item its text.
common.logger.info("CAPTCHA %s solved: %s" % (captcha["captcha"], captcha["text"]))
return captcha["text"].strip()
except deathbycaptcha.AccessDeniedException:
# Access to DBC API denied, check your credentials and/or balance
common.logger.info('Access to DBC API denied, check your credentials and/or balance')

def solve_recaptcha(html, D):
"""To solve the Google recaptcha
"""
m = re.compile(r']+src="(https?://www\.google\.com/recaptcha/api/noscript\?k=[^"]+)"', re.IGNORECASE).search(html)
if m:
common.logger.info('Need to solve the recaptcha.')
# need to solve the captcha first
iframe_url = m.groups()[0]
# load google recaptcha page
iframe_html = D.get(iframe_url, read_cache=False)
# extract recaptcha_challenge_field value for future use
recaptcha_challenge_field = xpath.get(iframe_html, '//input[@id="recaptcha_challenge_field"]/@value')
if recaptcha_challenge_field:
# extract captcha image link
captcha_image_url = xpath.get(iframe_html, '//img/@src')
if captcha_image_url:
captcha_image_url = urljoin(iframe_url, captcha_image_url)
# download captcha
captcha_bytes = D.get(captcha_image_url, read_cache=False)
if captcha_bytes:
#open('captcha.jpg', 'wb').write(captcha_bytes)
fileobj = StringIO.StringIO(captcha_bytes)
# read the captcha via deathbycaptcha
recaptcha_response_field = read_captcha(fileobj)
if recaptcha_response_field:
common.logger.info('Have got the captcha content = "%s".' % str(recaptcha_response_field))
url = 'https://www.linkedin.com/uas/captcha-submit'
post_data =
captcha_form = xpath.get(html, '//form[@name="captcha"]')
for input_name, input_value in re.compile(r']+type="hidden"\s+name="([^<>\"]+)"\s+value="([^<>\"]+)"').findall(captcha_form):
post_data[input_name] = input_value
post_data['recaptcha_challenge_field'] = recaptcha_challenge_field
post_data['recaptcha_response_field'] = recaptcha_response_field
return D.get(url, data=post_data, read_cache=False)
参考技术A 使用类似webkit的浏览器模拟工具(例如,phantomjs)加载页面,这样就能直接获取到JS生成的HTML源码。但是实现起来比较复杂,还需要借助第三方的软件。

如何在 Flutter 应用中实现 reCaptcha

【中文标题】如何在 Flutter 应用中实现 reCaptcha【英文标题】:How to implement reCaptcha into a flutter app 【发布时间】:2020-06-25 18:30:40 【问题描述】:

我正在尝试在我的颤振应用程序中实现 reCaptcha 功能,但在验证码注册中,我需要提供一个我没有用于移动应用程序的域。我浏览了几本指导如何将 reCaptcha 实施到移动应用程序中的指南,但这些指南使用包名称而不是域注册了他们的 reCaptcha。在 Flutter 应用或 2020 年的任何移动应用中实施 reCaptcha 的正确方法是什么?

【问题讨论】:

【参考方案1】:

你可以使用这个插件,flutter_recaptcha。

对于域,我遇到了同样的问题。我首先发现我需要使用here 中的“我不是机器人”复选框选项,并且我必须检查github repository 才能找到此信息,“!!!记得将此域添加到reCaptcha 设置:recaptcha-flutter-plugin.firebaseapp.com,”,它解释了它。

在主页上没有看到它后,我有点迷茫,但现在它是有道理的。希望对您有所帮助。

编辑

我在试用后注意到一些东西,我想提一下。该插件不提供用于验证用户服务器端的验证码响应,因此它看起来并不是很有用。但是,它是一个简单的插件,因此可以将其用作示例。我认为,这些步骤是创建一个带有验证码的网页。与插件一样,使用 webview 打开页面,然后捕获表单的发布输出和提交表单的用户的 IP 地址 using something like this,然后 send it to flutter,然后使用该信息提交您的请求,并使用Google library 验证验证码。

说明

我刚刚完成了这个,我找到了一个很好的方法。 首先,创建一个 html 页面,如下所示:

<html>
  <head>
    <title>reCAPTCHA</title>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
  </head>
  <body style='background-color: aqua;'>
    <div style='height: 60px;'></div>
    <form action="?" method="POST">
      <div class="g-recaptcha" 
        data-sitekey="YOUR-SITE-KEY"
        data-callback="captchaCallback"></div>

    </form>
    <script>
      function captchaCallback(response)
        //console.log(response);
        if(typeof Captcha!=="undefined")
          Captcha.postMessage(response);
        
      
    </script>
  </body>
</html>

然后,将其托管在您的域上,例如 example.com/captcha。

然后,创建一个flutter Widget,如下所示:

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class Captcha extends StatefulWidget
  Function callback;
  Captcha(this.callback);

  @override
  State<StatefulWidget> createState() 
    return CaptchaState();
  


class CaptchaState extends State<Captcha>
  WebViewController webViewController;
  @override
  initState()
    super.initState();
  


  @override
  Widget build(BuildContext context) 
    return Center(
      child: WebView(
        initialUrl: "https://example.com/captcha.html",
        javascriptMode: JavascriptMode.unrestricted,
        javascriptChannels: Set.from([
          JavascriptChannel(
            name: 'Captcha',
            onMessageReceived: (JavascriptMessage message) 
              //This is where you receive message from
              //javascript code and handle in Flutter/Dart
              //like here, the message is just being printed
              //in Run/LogCat window of android studio
              //print(message.message);
              widget.callback(message.message);
              Navigator.of(context).pop();
            )
        ]),
        onWebViewCreated: (WebViewController w) 
          webViewController = w;
        ,
      )
    );
  


确保您在https://www.google.com/recaptcha 注册了验证码(点击右上角的“管理控制台”)。

然后,您已经构建了前端。要调用验证码,只需运行:

Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context)
                      return Captcha((String code)=>print("Code returned: "+code));
                    
                  ),
                );

你可以使用任何你想要的回调,像这样:

class GenericState extends State<Generic>
void methodWithCaptcha(String captchaCode)
  // Do something with captchaCode


@override
  Widget build(BuildContext context) 
    return Center(child:FlatButton(
        child: Text("Click here!"),
        onPressed: ()
            Navigator.of(context).push(
                  MaterialPageRoute(
                    builder: (context)
                      return Captcha(methodWithCaptcha);
                    
                  ),
                );
        
  

服务器端,你可以按照here的说明进行操作(我按照“直接下载”和“使用”部分进行操作)。我发现对于用法,我可以简单地使用代码:

$recaptcha = new \ReCaptcha\ReCaptcha($secret);
$resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp);
if ($resp->isSuccess()) 
    // Verified!
 else 
    $errors = $resp->getErrorCodes();

没有必要像示例中那样使用setExpectedHostname

之后,一切正常!我认为这是目前在 Flutter 中实现 Google reCaptcha V2 的最佳方式(适用于 iOS 和 Android)。

【讨论】:

抱歉提出一个旧线程,但是否可以将此网页嵌入到应用程序中,这意味着不需要托管验证码页面?【参考方案2】:

如果你在找Flutter WEB,可以试试g_recaptcha_v3包

注意:

仅支持 reCAPTCHA V3,不支持 V2 仅适用于 Flutter Web,其他平台不支持

【讨论】:

以上是关于如何在程序中处理reCAPTCHA的主要内容,如果未能解决你的问题,请参考以下文章

在哪里处理 reCAPTCHA?在 JavaScript 中还是在 PHP 中?

如何将 Google Recaptcha v2 实施到限制访问 Google Recaptcha 的 Web 应用程序

如何在 Flutter web 中使用 ReCaptcha [重复]

如何在单页应用程序 (SPA) 中实现 ReCaptcha

如何绕过 Google reCAPTCHA 使用 Selenium 进行测试

如何将 Firebase 隐形 reCAPTCHA 用于 Angular Web 应用程序?