darkghosthunter/captchavel

该包已被废弃,不再维护。作者建议使用 laragear/recaptcha 包。

将reCAPTCHA集成到您的Laravel应用中,比大G本身还要好!

v7.0.3 2022-02-16 17:20 UTC

README

Captchavel

将reCAPTCHA集成到您的Laravel应用中,比大G本身还要好!

它使用您的Laravel HTTP客户端 async HTTP/2,使您的应用 更快。您只需要几行代码即可集成。

要求

  • Laravel 8.x,或更高版本
  • PHP 8.0,或更高版本

如果您需要支持旧版本,请考虑赞助或捐赠。

安装

您可以通过Composer安装此包

composer require darkghosthunter/captchavel

设置

将您的站点的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机制。

Captchavel已附带v2密钥用于本地开发。对于v3,您需要创建自己的凭证集。

使用

使用方法根据您是否使用复选框、不可见或Android挑战,或v3分数驱动挑战而有所不同。

复选框、不可见和Android挑战

在您将reCAPTCHA集成到前端或Android应用后,在提交包含reCAPTCHA的表单的POST路由中设置Captchavel中间件。中间件将捕获g-recaptcha-response输入(您稍后可以更改它)并检查它是否有效。

要声明中间件,请使用ReCaptcha辅助器以简化您的开发

  • ReCaptcha::checkbox()用于显式渲染复选框挑战。
  • ReCaptcha::invisible()用于不可见挑战。
  • ReCaptcha::android()用于Android应用挑战。
use App\Http\Controllers\Auth\LoginController;
use DarkGhostHunter\Captchavel\ReCaptcha;

Route::post('login', [LoginController::class, 'login'])
     ->middleware(ReCaptcha::checkbox());

Laravel 8.69或以下版本需要将对象转换为字符串。

记住挑战

为了避免表单反复要求挑战,您可以“记住”给定分钟数内的挑战。这可以在全局启用,但您可能更愿意按路由逐个执行。

简单使用 remember() 方法使用配置默认值。它接受分钟数来覆盖 全局参数。或者,rememberForever() 将永久记住挑战。

use App\Http\Controllers\Auth\LoginController;
use DarkGhostHunter\Captchavel\ReCaptcha;

Route::post('login', [LoginController::class, 'login'])
     ->middleware(ReCaptcha::invisible()->remember());

Route::post('message', [ChatController::class, 'login'])
     ->middleware(ReCaptcha::checkbox()->rememberForever());

您应结合使用 Blade 模板中的 @unlesschallenged 指令来使用此方法,以便在用户之前未成功完成挑战时渲染挑战。

@unlesschallenged
  <div class="g-recaptcha"
       data-sitekey="{{ recaptcha('invisible') }}"
       data-callback="onSubmit"
       data-size="invisible">
  </div>
@endchallenged

将挑战记住几分钟的好地方是在预期会失败的形式或用户可能跳转的多表单之间。

更改输入名称

您可以使用 input() 将输入名称从默认的 g-recaptcha-response 更改为任何名称。

use App\Http\Controllers\Auth\LoginController;
use DarkGhostHunter\Captchavel\ReCaptcha;

Route::post('login', [LoginController::class, 'login'])
     ->middleware(ReCaptcha::checkbox()->input('recaptcha_input'));

基于得分的挑战

reCAPTCHA v3 中间件与 v2 的工作方式不同。此响应始终是成功,但挑战分数在 0.01.0 之间。类似人类的交互将更高,而机器人的得分将更低。默认阈值是 0.5,但可以在全局或路由级别进行更改。

要开始使用它,只需在路由中使用 ReCaptcha::score() 方法。

use App\Http\Controllers\CommentController;
use DarkGhostHunter\Captchavel\ReCaptcha;

Route::post('comment', [CommentController::class, 'create'])
     ->middleware(ReCaptcha::score());

一旦在控制器中收到挑战,您将可以访问请求类或实例的两个方法:isHuman()isRobot(),它们返回 truefalse

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.
    $comment->moderated = $request->isRobot();
    
    $comment->save();
    
    return view('post.comment.show', ['comment' => $comment]);
}

您还可以通过 Captchavel 门面中的 response() 方法访问 reCAPTCHA 的响应。

use DarkGhostHunter\Captchavel\Facades\Captchavel;

$response = Captchavel::response();

if ($response->score > 0.2) {
    return 'Try again!';
}

阈值、操作和输入名称

中间件使用中间件助手接受三个额外的参数。

  1. threshold():必须 大于或等于 的值才被认为是人类。
  2. action():可选检查的操作名称。
  3. input():要验证的 reCAPTCHA 输入的名称。
use App\Http\Controllers\CommentController;use DarkGhostHunter\Captchavel\ReCaptcha;

Route::post('comment', [CommentController::class, 'create'])
     ->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\Captchavel\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 分数

您可以通过将 CAPTCHAVEL_FAKE 设置为 true 在本地开发中轻松伪造 reCAPTCHA 响应分数。

CAPTCHAVEL_FAKE=true

此环境变量更改了 reCAPTCHA 工厂以使用伪造的一个,这将伪造 reCAPTCHA 的成功响应,而不是解决真实挑战。

从那里,您可以通过在表单中填写 is_robot 输入来伪造机器人响应。

<form id="comment" method="post">
    <textarea name="body"></textarea>

    @env('local', 'testing')
        <input type="checkbox" name="is_robot" checked>
    @endenv

    <button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback='onSubmit'>
        Post comment
    </button>
</form>

前端集成

检查官方 reCAPTCHA 文档 以在前端或 Android 应用程序中集成 reCAPTCHA 脚本。

您可以使用 captchavel() 助手根据要渲染的挑战版本输出站点密钥:checkboxinvisibleandroidscore(v3)。

<form id='login' method="POST">
    <input type="email" name="email">
    <input type="password" name="password">

    <button class="g-recaptcha" data-sitekey="{{ captchavel('invisible') }}" data-callback='onSubmit'>
        Login
    </button>
</form>

您还可以使用 android 为 Android 应用程序检索密钥。

高级配置

Captchavel旨在即开即用,但您可以发布配置文件以微调reCAPTCHA验证。

php artisan vendor:publish --provider="DarkGhostHunter\Captchavel\CaptchavelServiceProvider" --tag="config"

您将获得一个包含此数组的配置文件

<?php

use DarkGhostHunter\Captchavel\Captchavel;

return [
    'enable'            => env('CAPTCHAVEL_ENABLE',  false),
    'fake'              => env('CAPTCHAVEL_FAKE', false),
    'hostname'          => env('RECAPTCHA_HOSTNAME'),
    'apk_package_name'  => env('RECAPTCHA_APK_PACKAGE_NAME'),
    'threshold'         => 0.5,
    'remember' => [
        'enabled' => false,
        'key'     => '_recaptcha',
        'minutes' => 10,
    ],
    'credentials'       => [
        // ...
    ]
];

启用开关

<?php

return [
    'enable' => env('CAPTCHAVEL_ENABLE', false),
];

默认情况下,Captchavel是禁用的,因此它不会检查reCAPTCHA挑战,并且在基于得分的路由上,它将始终解析为人类交互。

您可以通过CAPTCHAVEL_ENABLE环境变量来启用它。

CAPTCHAVEL_ENABLE=true

在某些本地或开发环境中启用它可能会很方便,以便使用包含的localhost测试密钥来检查实际交互,这些密钥仅在localhost上工作。

当关闭时,请求输入中不会验证reCAPTCHA v2挑战,因此您可以安全地忽略任何前端脚本或reCAPTCHA令牌或框。

伪造响应

CAPTCHAVEL_FAKE=true

如果启用了Captchavel,将此设置为true将允许您的应用程序从reCAPTCHA服务器伪造v3分数响应。对于v2挑战,将此设置为true将绕过挑战验证。

当运行单元测试时,此设置将自动设置为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挑战后“记住”用户是禁用的。

如果您预计只有一些路由需要记住挑战,而不是整个应用程序,建议您在每个路由的基础上使用“记住”

这还控制设置“记住”的时间(分钟)。当为零时,“记住”将持续到会话销毁或不再有效。

凭证

return [
    'credentials' => [
        // ...
    ]
];

以下是根据版本不同使用的reCAPTCHA凭证的全数组。除非您知道自己在做什么,否则不要更改此数组。

使用Captchavel测试分数

在测试期间,当Captchavel被禁用或启用但伪造时,设置了v2中间件的路线不需要在它们的主体中输入挑战,因为它们不会被验证。

reCAPTCHA v3(分数)响应始终伪造为人类,即使Captchavel被禁用。这保证了您始终可以访问控制器中的响应。

要修改测试中的分数,您应通过.env.testing环境文件或PHPUnit环境部分在测试中启用伪造,或者通过启用伪造。如果您使用其他测试框架,请参阅其文档。

<phpunit>
    <!-- ... -->
    <php>
        <env name="CAPTCHAVEL_ENABLE" value="true"/>
        <env name="CAPTCHAVEL_FAKE" value="true"/>
    </php>
</phpunit>

或者,您可以在单元测试之前更改配置。

public function test_this_route()
{
    $this->app['config']->set('captchavel.fake', true);
    
    // Do some testing...
}

在伪造挑战时,不需要在测试中添加任何reCAPTCHA令牌或密钥。

当使用reCAPTCHA v3(分数)时,您可以通过使用fakeHuman()fakeRobot()方法伪造由人类或机器人做出的响应,这些方法将分别为所有后续请求的分数设置为1.00.0

<?php

use DarkGhostHunter\Captchavel\Facades\Captchavel;

// Let the user login normally.
Captchavel::fakeHuman();

$this->post('login', [
    'email' => 'test@test.com',
    'password' => '123456',
])->assertRedirect('user.welcome');

// ... but if it's a robot, force him to use 2FA.
Captchavel::fakeRobot();

$this->post('login', [
    'email' => 'test@test.com',
    'password' => '123456',
])->assertViewIs('login.2fa');

伪造的响应不包含操作、主机名或APK包名,因此这些不会被验证。

手动伪造分数

或者,fakeScore()方法可以伪造您设置的任何分数的响应。

<?php

use DarkGhostHunter\Captchavel\Facades\Captchavel;

// A human comment should be public.
Captchavel::fakeScore(0.7);

$this->post('comment', [
    'body' => 'This comment was made by a human',
])->assertSee('Your comment has been posted!');

// A robot should have its comment moderated.
Captchavel::fakeScore(0.4);

$this->post('comment', [
    'body' => 'Comment made by robot.',
])->assertSee('Your comment will be reviewed before publishing.');

安全

如果您发现任何与安全相关的问题,请通过电子邮件发送至darkghosthunter@gmail.com,而不是使用问题跟踪器。

许可

MIT许可(MIT)。有关更多信息,请参阅许可文件