实施Google reCAPTCHA
由于机器人攻击,我们决定引入reCAPTCHA来响应大量应用程序,因此我们将描述该过程。
如果您不知道如何实现reCAPTCHA ..,则可能会有所帮助。
有v2和v3,但我想尽可能避免用户的应用程序,并采取最小的机器人对策,因此
在v2的隐藏版本中实现。
这次不涉及v2复选框和v3方法。
为了清楚起见,以PHP框架Laravel为例,但我认为可以以其他方式在其他框架和所谓的Vanilla PHP中实现。
环境假定为LAMP。
Google reCAPTCHA隐形设置程序
管理屏幕上的设置
首先,我们必须为每个站点发布一个API密钥,因此我们将在管理屏幕上进行设置。
访问Google reCAPTCHA网站。
https://www.google.com/recaptcha/intro/v3.html
转到管理控制台并添加一个新站点,
"标签"可以是您喜欢的任何名称。
"安全设置"具有3个级别,
当我将其设置为2到3时,有时用户的应用程序会被图像身份验证拒绝,因此
我们决定将其设置为一个"最小用户负担"的级别。
确认上述内容后,将发布API站点密钥和秘密密钥。
接下来,我们将在Laravel上进行设置。
JS标签
的安装
首先,加载API JS文件。
插入模板文件的
资源/视图/表单/input.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> FooBar Form + <script src="https://www.google.com/recaptcha/api.js" async defer></script> </head> <body> // contents <form action="entry/input/" method="post" id="form"> // form inputs </form> </body> </html> |
前标签脚本设置
设置配置
由于最好不要管理
API密钥的版本,因此请使用
.env
1 2 | + APP_RECAPTCHA_SITE_KEY=your_site_key + APP_RECAPTCHA_SECRET_KEY=your_secret_key |
读取设置的文件。
API端点也在此处设置。
config / app.php
1 2 3 4 5 6 7 8 9 10 11 12 | /* |-------------------------------------------------------------------------- | reCAPTCHA Settings |-------------------------------------------------------------------------- |*/ + 'recaptcha' => [ + 'api_url' => 'https://www.google.com/recaptcha/api/siteverify', + 'site_key' => env('APP_RECAPTCHA_SITE_KEY'), + 'secret_key' => env('APP_RECAPTCHA_SECRET_KEY'), + ], ]; |
ReCAPTCHA div标签安装将呈现
ReCAPTCHA是渲染所必需的,因此进行设置。
资源/视图/表单/input.blade.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!doctype html> <html lang="{{ str_replace('_', '-', app()->getLocale()) }}"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> FooBar Form <script src="https://www.google.com/recaptcha/api.js" async defer></script> </head> <body> // contents <form action="./entry/input" method="post" id="form"> + <div class="g-recaptcha" + data-sitekey="{{ config('app.recaptcha.site_key') }}" + data-callback="onGrecaptchaSubmit" + data-size="invisible"></div> // form inputs </form> </body> </html> |
调用reCAPTCHA
的API设置
全局定义回调函数。
另外,就我而言,我正在应用JS验证,
我希望不是在"按下提交按钮时"而是在"通过验证时"触发reCAPTCHA API,所以
使用
reCAPTCHA提供的
资源/ js / form-efo.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | + window.onGrecaptchaSubmit = function(request) { + $('form').submit(); + }; $(() => { // 省略??? if (validated()) { // 省略??? - $('form').submit(); + grecaptcha.execute(); } // ??? }); |
这样就完成了正面的设置。
如果在本地环境中查看它,您将在右下角看到reCAPTCHA图标。
通常,如果有人输入并提交,它将按原样进行,但是
如果执行自动输入等,将会出现图像认证画面并被抓住。
后端侧reCAPTCHA身份验证实现
由于可能仅在客户端进行未经授权的突破,因此也请在后端检查身份验证。
简而言之,当reCAPTCHA API在客户端触发时,将发出令牌,
提交表单时,令牌是用键
中间件创建
有各种各样的方法,但是这次我们将使用中间件。
我正在使用
根据发布的密钥,在客户端发布的令牌和IP地址,检查是否有无效的提交。
如果您想了解有关
API的更多信息,请参考官方文档。
https://developers.google.com/recaptcha/docs/verify
应用程序/ Http /中间件/ CheckRecaptcha.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | <?php namespace App\Http\Middleware; use Closure; class CheckRecaptcha { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->input('g-recaptcha-response')){ $secret_key = config('app.recaptcha.secret_key'); $url = config('app.recaptcha.api_url'); $token = $request->input('g-recaptcha-response'); $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'secret' => $secret_key, 'response' => $token, 'remoteip' => $request->server->get('REMOTE_ADDR'), ]), ]); $_response = curl_exec($ch); curl_close($ch); $response = json_decode($_response); if (isset($response->success) && $response->success) { return $next($request); } else { return redirect('error'); // エラーページへリダイレクト } } return redirect('error'); // エラーページへリダイレクト } } |
从这里开始,仅涉及Laravel,因此,如果它是另一个框架,则可以跳过。
在
内核和
中注册中间件
应用程序/ Http / Kernel.php
1 2 3 4 5 6 7 8 9 10 11 | /** * The application's route middleware. * * These middleware may be assigned to groups or used individually. * * @var array */ protected $routeMiddleware = [ // 省略??? + 'recaptcha' => \App\Http\Middleware\CheckRecaptcha::class, ]; |
将中间件分配给应用程序表单的路由。
路线/ web.php
1 2 3 | - Route::post('/entry/input', [\App\Http\Controllers\EntryInputController::class, 'input'])->name('entry.input'); + Route::post('/entry/input', [\App\Http\Controllers\EntryInputController::class, 'input'])->name('entry.input') + ->middleware('recaptcha'); |
这样就完成了reCAPTCHA身份验证设置。
补充:设置输出日志
在后端执行API身份验证时,您可能希望输出响应的内容。
就我而言,我将日志输出设置如下。
如果发生身份验证错误,您可以看到状态代码和错误详细信息,这将使调试更加容易。
应用程序/ Http /中间件/ CheckRecaptcha.php
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next) { if ($request->input('g-recaptcha-response')){ $secret_key = config('app.recaptcha.secret_key'); $url = config('app.recaptcha.api_url'); $token = $request->input('g-recaptcha-response'); $ch = curl_init(); curl_setopt_array($ch, [ CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, CURLOPT_POSTFIELDS => http_build_query([ 'secret' => $secret_key, 'response' => $token, 'remoteip' => $request->server->get('REMOTE_ADDR'), ]), ]); $_response = curl_exec($ch); + $_error = curl_error($ch); curl_close($ch); $response = json_decode($_response); + Log::info( + $_response ? [ + 'recaptcha-result' => $response->success ? $response->success : $response['error-codes'] + ] : ['recaptcha-error' => $_error] + ); + return is_null($response) ? false : $response->success; } return false; } |
使用Laravel!轻松实现Google reCAPTCHA!
这次,我将其设置为隐藏v2的安全级别1,但是Selenium机器人也可以播放它,没有用户无法申请的事情。
Bot对策可以通过相对简单的实现来采取,因此请尝试一下。
*参考页
https://developers.google.com/recaptcha/docs/invisible
没有日文版本,因此我这次进行了总结。