laragear / recaptcha
使用异步HTTP/3集成reCAPTCHA,用几行代码使您的应用快速。
Requires
- php: ^8.1
- ext-json: *
- guzzlehttp/guzzle: ^7.5
- illuminate/container: 10.*|11.*
- illuminate/events: 10.*|11.*
- illuminate/http: 10.*|11.*
- illuminate/routing: 10.*|11.*
- illuminate/support: 10.*|11.*
Requires (Dev)
- orchestra/testbench: 8.*|9.*
README
使用异步HTTP/3 async HTTP/3 集成reCAPTCHA,用几行代码使您的应用 快速。
use Illuminate\Support\Facades\Route; Route::post('login', function () { // ... })->middleware('recaptcha:checkbox');
成为赞助商
您的支持使我能够保持这个包免费、更新和可维护。或者,您可以 传播这个消息!
要求
- Laravel 10 或更高版本
安装
您可以通过Composer安装此包
composer require laragear/recaptcha
设置
将您网站的reCAPTCHA密钥添加到项目的环境文件中。您可以分别为reCAPTCHA v2的 复选框、隐藏、Android 和 评分 添加每个密钥。
如果您还没有,可以在您的 reCAPTCHA 管理面板 中生成它。
RECAPTCHA_CHECKBOX_SECRET=6t5geA1UAAAAAN... RECAPTCHA_CHECKBOX_KEY=6t5geA1UAAAAAN... RECAPTCHA_INVISIBLE_SECRET=6t5geA2UAAAAAN... RECAPTCHA_INVISIBLE_KEY=6t5geA2UAAAAAN... RECAPTCHA_ANDROID_SECRET=6t5geA3UAAAAAN... RECAPTCHA_ANDROID_KEY=6t5geA3UAAAAAN... RECAPTCHA_SCORE_SECRET=6t5geA4UAAAAAN... RECAPTCHA_SCORE_KEY=6t5geA4UAAAAAN...
这允许您在不同的环境中使用同一应用程序检查不同的reCAPTCHA机制。
注意
ReCaptcha已经包含了v2密钥用于本地开发。对于v3,您需要在生产环境中创建自己的凭证集。
用法
用法取决于您是否使用复选框、隐藏、Android挑战或v3评分驱动挑战。
复选框、隐藏和Android挑战
在将reCAPTCHA集成到您的前端或Android应用后,在提交带有reCAPTCHA的表单的 POST
路由中设置ReCaptcha中间件。中间件将捕获 g-recaptcha-response
输入(您稍后可以更改它)并检查它是否有效。
只需使用 ReCaptcha
中间件构建器即可声明中间件
ReCaptcha::checkbox()
用于显式渲染的复选框挑战。ReCaptcha::invisible()
用于隐藏挑战。ReCaptcha::android()
用于Android应用挑战。
use App\Http\Controllers\ContactController; use Laragear\ReCaptcha\Http\Middleware\Builders\ReCaptcha; use Illuminate\Support\Facades\Route; Route::post('contact', [ContactController::class, 'send']) ->middleware(ReCaptcha::invisible()->forGuests('web')->remember())
如果由于某种原因挑战未成功,验证将立即启动并抛出 ValidationException
,将用户返回到表单。
记住挑战
为了避免反复要求挑战,您可以“记住”给定分钟的挑战。这可以在全局范围内启用,但您可能更喜欢按路由基础进行。
简单使用 remember()
方法。您可以设置分钟数以覆盖全局参数。或者,rememberForever()
将永远记住挑战。
use App\Http\Controllers\Auth\LoginController; use Laragear\ReCaptcha\Http\Middleware\Builders\ReCaptcha; use Illuminate\Support\Facades\Route Route::post('login', [LoginController::class, 'login']) ->middleware(ReCaptcha::invisible()->remember()); Route::post('message', [ChatController::class, 'login']) ->middleware(ReCaptcha::checkbox()->rememberForever());
您应该将此与Blade模板中的 @robot
指令结合使用,以便在用户之前未成功完成挑战时渲染挑战。
@robot <div class="g-recaptcha" data-sitekey="{{ recaptcha('invisible') }}" data-callback="onSubmit" data-size="invisible"> </div> @endrobot
提示
将挑战记住几分钟的好地方是预期会失败的表单,或者当用户可能在多个表单之间跳转时。
更改输入名称
您可以使用 input()
将输入名称从默认的 g-recaptcha-response
更改为任何内容。
use App\Http\Controllers\Auth\LoginController; use Laragear\ReCaptcha\Http\Middleware\Builders\ReCaptcha; use Illuminate\Support\Facades\Route Route::post('login', [LoginController::class, 'login']) ->middleware(ReCaptcha::checkbox()->input('recaptcha_input'));
评分驱动挑战
reCAPTCHA v3 中间件的工作方式与 v2 不同。此响应始终是成功,但挑战分数介于 0.0
和 1.0
之间。类似人类的交互将更高,而机器人的分数将更低。默认阈值是 0.5
,但可以在全局或按路由更改。
要开始使用它,只需在您的路由中使用 ReCaptcha::score()
方法。
use App\Http\Controllers\CommentController; use Laragear\ReCaptcha\Http\Middleware\Builders\ReCaptcha; use Illuminate\Support\Facades\Route Route::post('comment', [CommentController::class, 'create']) ->middleware(ReCaptcha::score());
一旦挑战已发送到您的控制器,您将能够访问请求类或实例的两种方法:isHuman()
和 isRobot()
,它们可能返回 true
或 false
use App\Models\Post; use Illuminate\Http\Request; public function store(Request $request, Post $post) { $request->validate([ 'body' => 'required|string|max:255' ]); $comment = $post->comment()->make($request->only('body')); // Flag the comment as "moderated" if it was a written by robot. if ($request->isRobot()) { $comment->markAsModerated(); } $comment->save(); return view('post.comment.show', ['comment' => $comment]); }
您还可以通过 ReCaptcha
门面的 response()
方法访问 reCAPTCHA 的响应
use Laragear\ReCaptcha\Facades\ReCaptcha; $response = ReCaptcha::response(); if ($response->score > 0.2) { return 'Try again!'; }
警告
请小心调用 response()
,因为它会在没有挑战的控制器上抛出异常。
阈值、操作和输入名称
中间件通过中间件助手接受三个额外的参数。
threshold()
:必须大于或等于此值才能被认为是人类。action()
:可选地检查的操作名称。input()
:要验证的 reCAPTCHA 输入的名称。
use App\Http\Controllers\CommentController; use Laragear\ReCaptcha\Http\Middleware\Builders\ReCaptcha; use Illuminate\Support\Facades\Route Route::post('comment', [CommentController::class, 'store']) ->middleware(ReCaptcha::score()->threshold(0.7)->action('post-comment')->input('my_score_input');
重要
在检查操作名称时,请确保您的前端操作与中间件中预期的匹配。
绕过认证用户
有时您可能希望在存在认证用户的情况下绕过 reCAPTCHA 检查,或者在基于分数的挑战中自动将其视为“人类”,尤其是在重复操作或用户已经完成挑战的情况下(例如在登录时)。
要排除认证用户,可以使用 forGuests()
,并根据需要指定保护者。
use App\Http\Controllers\CommentController; use App\Http\Controllers\MessageController; use DarkGhostHunter\Captcha\ReCaptcha; use Illuminate\Support\Facades\Route // Don't challenge users authenticated on the default (web) guard. Route::post('message/send', [MessageController::class, 'send']) ->middleware(ReCaptcha::invisible()->forGuests()); // Don't challenge users authenticated on the "admin" and "moderator" guards. Route::post('comment/store', [CommentController::class, 'store']) ->middleware(ReCaptcha::score(0.7)->action('comment.store')->forGuests('admin', 'moderator'));
然后,在您的 blade 文件中,您可以使用 @guest
或 @auth
指令轻松跳过挑战。
<form id="comment" method="post"> <textarea name="body"></textarea> @auth <button type="submit">Post comment</button> @else <button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback="onSubmit"> Post comment </button> @endauth </form>
伪造 reCAPTCHA 分数
您可以通过将 RECAPTCHA_FAKE
设置为 true
来轻松伪造本地开发中的 reCAPTCHA 响应分数。
RECAPTCHA_FAKE=true
此环境变量允许通过填写表单中的 is_robot
输入来伪造机器人响应。
<form id="comment" method="post"> <textarea name="body"></textarea> @env('local') <input type="checkbox" name="is_robot" checked> @endenv <button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback='onSubmit'> Post comment </button> </form>
确认中间件
ReCaptcha 附带了一个方便的中间件,通过简单的 reCAPTCHA 复选框挑战进行确认,就像 Laravel 中包含的 密码确认 中间件一样。
首先,使用 recaptcha.confirm
中间件设置要保护的路由。
use Illuminate\Support\Facades\Route; Route::get('/settings', function () { // ... })->middleware('recaptcha.confirm'); Route::post('/settings', function () { // ... })->middleware('recaptcha.confirm');
完成操作后,确保您还有一个 recaptcha.confirm
路由来接收重定向的用户,以及一个接收挑战的路由,该路由与路径相同(如视图 POST
请求所做的那样)。ReCaptcha 附带了一个控制器和一个基本视图,您可以直接使用。
use Illuminate\Support\Facades\Route; use Laragear\ReCaptcha\Http\Controllers\ConfirmationController; Route::get('recaptcha', [ConfirmationController::class, 'show']) ->name('recaptcha.confirm'); Route::post('recaptcha', [ConfirmationController::class, 'confirm'])
当用户尝试进入路由时,它将被重定向到请求解决 reCAPTCHA 挑战的视图。完成后,它将被重定向到目标 URL。
该中间件与 记住挑战 兼容,并且如果全局启用,它将使用默认的时间量不再次请求,否则每次都会要求确认。
您可以在第一个参数之后配置路由名称和保护者,以便在用户认证后绕过确认。
use Illuminate\Support\Facades\Route; Route::get('/settings', function () { // ... })->middleware('recaptcha.confirm:my-custom-route,web,admin');
前端集成
请参阅 官方 reCAPTCHA 文档 以在您的前端或 Android 应用程序中集成 reCAPTCHA 脚本。
您可以使用 recaptcha()
助手根据您要渲染的挑战版本输出站点密钥:checkbox
、invisible
、android
或 score
(v3)。
<form id='login' method="POST"> <input type="email" name="email"> <input type="password" name="password"> <button class="g-recaptcha" data-sitekey="{{ recaptcha('invisible') }}" data-callback='onSubmit'> Login </button> </form>
高级配置
ReCaptcha 旨在开箱即用,但您可以将配置文件发布以微调 reCAPTCHA 验证。
php artisan vendor:publish --provider="Laragear\ReCaptcha\ReCaptchaServiceProvider" --tag="config"
您将获得一个包含此数组的配置文件
<?php return [ 'enable' => env('RECAPTCHA_ENABLE', false), 'fake' => env('RECAPTCHA_FAKE', false), 'hostname' => env('RECAPTCHA_HOSTNAME'), 'apk_package_name' => env('RECAPTCHA_APK_PACKAGE_NAME'), 'threshold' => 0.5, 'remember' => [ 'enabled' => false, 'key' => '_recaptcha', 'minutes' => 10, ], 'client' => [ 'version' => 2.0, ], 'credentials' => [ // ... ] ];
启用开关
return [ 'enable' => env('RECAPTCHA_ENABLE', false), ];
默认情况下,ReCaptcha是禁用的,因此它不会检查reCAPTCHA挑战,在基于得分的路由上,它始终将其解析为人类交互。
您可以通过RECAPTCHA_ENABLE
环境变量来启用它。
RECAPTCHA_ENABLE=true
在某些本地或开发环境中启用它可能很有用,以检查使用包含的localhost测试密钥的真实交互,这些密钥只能在localhost
上工作。
重要
当关闭时,reCAPTCHA v2挑战不会在请求输入中进行验证,因此您可以安全地忽略任何前端脚本或reCAPTCHA令牌或框。
伪造响应
RECAPTCHA_FAKE=true
如果启用了ReCaptcha,将此设置为true将允许您的应用程序从reCAPTCHA服务器伪造v3-score响应。对于v2挑战,将此设置为true
将绕过挑战验证。
您应该在运行单元测试时启用它。
警告
请记住在生产环境中禁用伪造。如果不这样做,将伪造所有得分挑战为人类,不需要挑战令牌。
主机名和APK包名
RECAPTCHA_HOSTNAME=myapp.com RECAPTCHA_APK_PACKAGE_NAME=my.package.name
如果您在reCAPTCHA管理面板中未验证主机名或APK包名,可能是因为您使用多个主机名或应用程序,您必须在环境文件中指定它们。
当从服务器检索reCAPTCHA响应时,如果存在,将检查这些值。如果存在不匹配,将抛出验证异常。
阈值
return [ 'threshold' => 0.4 ];
检查reCAPTCHA v3挑战的默认阈值。值等于或高于将被视为“人类”。
如果您不使用reCAPTCHA v3或您对此默认值满意,请勿更改。您仍然可以根据路由覆盖默认值。
记住
return [ 'remember' => [ 'enabled' => false, 'key' => '_recaptcha', 'minutes' => 10, ], ];
默认情况下,成功完成V2挑战后记住用户是禁用的。
如果您期望只有一些路由记住挑战,而不是整个应用程序,建议您按路由使用“记住”。
这还控制了设置“记住”的分钟数。您可以将INF
常量设置为永远记住挑战(或直到会话过期)。
HTTP客户端选项
return [ 'client' => [ 'version' => 3.0, ], ];
此数组设置对reCAPTCHA服务器的请求的选项。这是由Guzzle处理的,它反过来将它们传递给底层传输。根据您的系统,它可能是cURL。
默认情况下,它指示Guzzle尽可能使用HTTP/3。
凭据
return [ 'credentials' => [ // ... ] ];
以下是根据版本使用完整reCAPTCHA凭据的数组。除非您知道自己在做什么,否则不要更改此数组。
使用ReCaptcha v2进行开发
在本地开发中,使用默认的测试密钥。这些密钥旨在用于本地开发,因此在生产环境中可以轻松地将它们更改为真实密钥。
在单元测试中,中间件将检测环境并跳过强制性的挑战检查。无需禁用ReCaptcha。
使用ReCaptcha v3(得分)进行开发
在本地开发和单元测试中,中间件将自动创建人工响应。无需禁用ReCaptcha,但为了使用is_robot
在实时请求中启用模拟机器人响应,启用模拟是强制性的。
在您的测试中,您可以通过简单地使用fakeHuman()
和fakeRobot()
方法来模拟由人工或机器人发出的响应,这些方法将为后续请求分别评分1.0
或0.0
。
<?php use Laragear\ReCaptcha\Facades\ReCaptcha; // Let the user login normally. ReCaptcha::fakeHuman(); $this->post('login', [ 'email' => 'test@test.com', 'password' => '123456', ])->assertRedirect('user.welcome'); // ... but if it's a robot, force him to use 2FA. ReCaptcha::fakeRobot(); $this->post('login', [ 'email' => 'test@test.com', 'password' => '123456', ])->assertViewIs('login.2fa');
注意
模拟响应不包含操作、主机名或APK包名,因此这些不会被验证。
或者,使用fakeScore()
方法可以模拟您设置的任何分数的响应。
<?php use Laragear\ReCaptcha\Facades\ReCaptcha; // A human comment should be public. ReCaptcha::fakeScore(0.8); $this->post('comment', [ 'body' => 'This comment was made by a human', ])->assertSee('Your comment has been posted!'); // Moderate a post if there is no clear separation. ReCaptcha::fakeScore(0.4); $this->post('comment', [ 'body' => 'Comment made by something.', ])->assertSee('Your comment will be reviewed before publishing.'); // A robot shouldn't be able to comment. ReCaptcha::fakeScore(0.2); $this->post('comment', [ 'body' => 'Comment made by robot.', ])->assertSee('Robots are not welcomed here! Go away!');
PhpStorm存根
对于PhpStorm用户,有一个存根文件和一个元文件来帮助自动补全此包的宏。您可以使用phpstorm
标签来发布它们。
php artisan vendor:publish --provider="Laragear\ReCaptcha\ReCaptchaServiceProvider" --tag="phpstorm"
该文件将发布到您项目的.stubs
文件夹中,而元文件位于.phpstorm.meta.php
目录中。您应该将PhpStorm指向这些存根。
Laravel Octane兼容性
- 唯一注册的单例是使用过时配置实例的
ReCaptcha
类。您不应该更改配置。 - 在请求过程中没有写入静态属性。
使用Laravel Octane时,应无任何问题使用此包。
HTTP/3和cURL
要使用HTTP/3,请确保您正在使用PHP 8.2或更高版本确保您使用PHP 8.2或更高版本。cURL版本7.66支持HTTP/3,而最新的PHP 8.2使用版本7.85。
有关检查您的平台是否可以发出HTTP/3请求的更多信息,请查看此PHP Watch文章。
安全性
如果您发现任何安全问题,请通过电子邮件darkghosthunter@gmail.com报告,而不是使用问题跟踪器。
许可
此特定包版本根据发布时的MIT许可证进行许可。
Laravel是Taylor Otwell的商标。版权所有©2011-2024 Laravel LLC。