spatie / laravel-honeypot
防止通过表单提交的垃圾邮件
Requires
- php: ^8.0
- illuminate/contracts: ^8.0|^9.0|^10.0|^11.0
- illuminate/encryption: ^8.0|^9.0|^10.0|^11.0
- illuminate/http: ^8.0|^9.0|^10.0|^11.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0
- illuminate/validation: ^8.0|^9.0|^10.0|^11.0
- nesbot/carbon: ^2.0|^3.0
- spatie/laravel-package-tools: ^1.9
- symfony/http-foundation: ^5.1.2|^6.0|^7.0
Requires (Dev)
- livewire/livewire: ^2.10|^3.0
- orchestra/testbench: ^6.23|^7.0|^8.0|^9.0
- pestphp/pest-plugin-livewire: ^1.0|^2.1
- phpunit/phpunit: ^9.6|^10.5
- spatie/pest-plugin-snapshots: ^1.1|^2.1
- spatie/phpunit-snapshot-assertions: ^4.2|^5.1
- spatie/test-time: ^1.2.1
README
当将表单添加到公共网站时,垃圾邮件机器人可能会尝试使用虚假值提交它。幸运的是,这些机器人中的大多数都很笨。你可以在表单中添加一个不可见的字段,该字段在提交时不应包含任何值。这样的字段被称为蜜罐。这些垃圾邮件机器人将填写所有字段,包括蜜罐。
当收到包含已填充蜜罐字段的提交时,此包将丢弃该请求。此外,此包还会检查表单提交所需的时间。这是通过另一个不可见的字段中的时间戳来完成的。如果表单提交时间异常短,反垃圾邮件也将被触发。
安装此包后,你只需将 x-honeypot
Blade 组件添加到你的表单中。
<form method="POST"> <x-honeypot /> <input name="myField" type="text"> </form>
此包还支持手动将必要的值传递到视图层,因此你可以轻松地将蜜罐字段添加到由 Inertia 驱动的应用程序中。
支持我们
我们投入了大量资源来创建 一流的开源包。你可以通过 购买我们的付费产品之一 来支持我们。
我们非常感谢你从家乡寄来明信片,说明你正在使用我们哪个包。你可以在 我们的联系页面 上找到我们的地址。我们将把所有收到的明信片发布在 我们的虚拟明信片墙上。
视频教程
在 此视频 中,这是 Mailcoach 视频课程的一部分,你可以看到如何安装和使用此包。
安装
您可以通过 composer 安装此包
composer require spatie/laravel-honeypot
可选,您可以发布包的配置文件。
php artisan vendor:publish --provider="Spatie\Honeypot\HoneypotServiceProvider" --tag=config
这是将在 config/honeypot.php
发布的配置文件内容
use Spatie\Honeypot\SpamResponder\BlankPageResponder; return [ /* * Here you can specify name of the honeypot field. Any requests that submit a non-empty * value for this name will be discarded. Make sure this name does not * collide with a form field that is actually used. */ 'name_field_name' => env('HONEYPOT_NAME', 'my_name'), /* * When this is activated there will be a random string added * to the name_field_name. This improves the * protection against bots. */ 'randomize_name_field_name' => env('HONEYPOT_RANDOMIZE', true), /* * When this is activated, requests will be checked if * form is submitted faster than this amount of seconds */ 'valid_from_timestamp' => env('HONEYPOT_VALID_FROM_TIMESTAMP', true), /* * This field contains the name of a form field that will be used to verify * if the form wasn't submitted too quickly. Make sure this name does not * collide with a form field that is actually used. */ 'valid_from_field_name' => env('HONEYPOT_VALID_FROM', 'valid_from'), /* * If the form is submitted faster than this amount of seconds * the form submission will be considered invalid. */ 'amount_of_seconds' => env('HONEYPOT_SECONDS', 1), /* * This class is responsible for sending a response to requests that * are detected as being spammy. By default a blank page is shown. * * A valid responder is any class that implements * `Spatie\Honeypot\SpamResponder\SpamResponder` */ 'respond_to_spam_with' => BlankPageResponder::class, /* * This class is responsible for applying all protection * rules for a request. By default uses `request()`. * * It throws the `Spatie\Honeypot\ExceptionsSpamException` if the * request is flagged as spam, or returns void if it succeeds. */ 'spam_protection' => \Spatie\Honeypot\SpamProtection::class, /* * When activated, requests will be checked if honeypot fields are missing, * if so the request will be stamped as spam. Be careful! When using the * global middleware be sure to add honeypot fields to each form. */ 'honeypot_fields_required_for_all_forms' => false, /* * This switch determines if the honeypot protection should be activated. */ 'enabled' => env('HONEYPOT_ENABLED', true), ];
使用
首先,您必须将 x-honeypot
Blade 组件添加到您想要保护的任何表单中。
<form method="POST" action="{{ route('contactForm.submit') }}")> <x-honeypot /> <input name="myField" type="text"> </form>
或者,您可以使用 @honeypot
Blade 指令
<form method="POST" action="{{ route('contactForm.submit') }}")> @honeypot <input name="myField" type="text"> </form>
使用 Blade 组件或指令将添加两个字段: my_name
和 valid_from_timestamp
(您可以在配置文件中更改名称)。
接下来,您必须在处理表单提交的路由中使用 Spatie\Honeypot\ProtectAgainstSpam
中间件。此中间件将拦截任何提交非空值给 my_name
键的请求。如果请求提交速度比包在 valid_from_timestamp
中生成的加密时间戳要快,它也会拦截请求。
use App\Http\Controllers\ContactFormSubmissionController; use Spatie\Honeypot\ProtectAgainstSpam; Route::post('contact', [ContactFormSubmissionController::class, 'create'])->middleware(ProtectAgainstSpam::class);
如果您想将 Spatie\Honeypot\ProtectAgainstSpam
中间件与 Laravel 内置的认证路由集成,请将 Auth::routes();
声明包裹在适当的中间件组中(确保将 @honeypot
指令添加到认证表单中)。
use Spatie\Honeypot\ProtectAgainstSpam; Route::middleware(ProtectAgainstSpam::class)->group(function() { Auth::routes(); });
如果您的应用程序有大量由许多不同控制器处理的表单,您可以将其注册为全局中间件。
// inside app\Http\Kernel.php protected $middleware = [ // ... \Spatie\Honeypot\ProtectAgainstSpam::class, ];
Inertia 中的使用
当使用Inertia时,您必须手动传递用于蜜罐字段的值。以下是一个示例
// in a controller public function create(\Spatie\Honeypot\Honeypot $honeypot) { return inertia('contactform.show', [ 'honeypot' => $honeypot, ]); }
您的前端将获得一个具有以下键的honeypot
对象:enabled
、nameFieldName
、validFromFieldName
、encryptedValidFrom
。
以下是如何使用Vue渲染这些值的示例
<div v-if="honeypot.enabled" :name="`${honeypot.nameFieldName}_wrap`" style="display:none;"> <input type="text" v-model="form[honeypot.nameFieldName]" :name="honeypot.nameFieldName" :id="honeypot.nameFieldName" /> <input type="text" v-model="form[honeypot.validFromFieldName]" :name="honeypot.validFromFieldName" /> </div>
然后在您的Vue组件中,将这些值添加到表单数据中
props: ['honeypot'], data() { return { form: this.$inertia.form({ [this.honeypot.nameFieldName]: '', [this.honeypot.validFromFieldName]: this.honeypot.encryptedValidFrom, }), } }
在Livewire中的使用
您可以使用此包来防止向由Livewire提供的表单提交垃圾邮件。
首先,将UsesSpamProtection
特性添加到您的Livewire组件中
use Spatie\Honeypot\Http\Livewire\Concerns\UsesSpamProtection; class YourComponent extends Component { use UsesSpamProtection;
接下来,声明一个HoneypotData
属性,并在处理表单提交的方法中调用protectAgainstSpam()
use Spatie\Honeypot\Http\Livewire\Concerns\HoneypotData; class YourComponent extends Component { // ... public HoneypotData $extraFields; public function mount() { $this->extraFields = new HoneypotData(); } public function submit(): void { $this->protectAgainstSpam(); // if is spam, will abort the request User::create($request->all()); } }
最后,在您的Livewire Blade组件中使用x-honeypot
<form method="POST" action="{{ route('contactForm.submit') }}")> <x-honeypot livewire-model="extraFields" /> <input name="myField" type="text"> </form>
在Volt函数语法中的使用
要在Volt函数语法中使用此包,从guessHoneypotDataProperty
方法返回HoneypotData
属性。
use App\Models\User; use Spatie\Honeypot\Http\Livewire\Concerns\HoneypotData; use Spatie\Honeypot\Http\Livewire\Concerns\UsesSpamProtection; use function Livewire\Volt\{uses, state, mount}; uses(UsesSpamProtection::class); state([ // ... 'extraFields' => null, ]); mount(function () { $this->extraFields = new HoneypotData(); }); $guessHoneypotDataProperty = fn () => $this->extraFields; $submit = function () { $this->protectAgainstSpam(); // if is spam, will abort the request User::create($request->all()); };
测试中禁用
默认情况下,任何在1秒内提交的保护表单将被标记为垃圾邮件。当运行端到端测试时,这些测试应尽可能快地运行,您可能不希望这样。
要禁用代码中的所有蜜罐,可以将enabled
配置值设置为false
。
config()->set('honeypot.enabled', false)
自定义响应
当检测到垃圾邮件提交时,该包默认将显示一个空白页面。您可以通过编写自己的SpamResponse
并指定其完全限定类名在honeypot
配置文件的respond_to_spam_with
键中来自定义此行为。
有效的SpamResponse
是实现了Spatie\Honeypot\SpamResponder\SpamResponder
接口的任何类。以下是这个接口的样子
namespace Spatie\Honeypot\SpamResponder; use Closure; use Illuminate\Http\Request; interface SpamResponder { public function respond(Request $request, Closure $next); }
尽管垃圾邮件响应者的主要目的是响应垃圾邮件请求,但您也可以在这里做其他事情。例如,您可以使用$request
上的属性来确定垃圾邮件的来源(例如,所有请求都来自同一个IP),并添加一些逻辑来阻止该来源。
如果该包错误地确定了请求是垃圾邮件,您可以像在中间件中那样传递$request
到$next
闭包来生成默认响应。
// in your spam responder $regularResponse = $next($request)
自定义生成的蜜罐字段
要自定义输出,可以使用以下命令发布honeypot
视图
php artisan vendor:publish --provider="Spatie\Honeypot\HoneypotServiceProvider" --tag=honeypot-views
视图将放置在resources/views/vendor/honeypot/honeypotFormFields.blade.php
。这是默认内容
@if($enabled) <div id="{{ $nameFieldName }}_wrap" style="display:none;"> <input name="{{ $nameFieldName }}" type="text" value="" id="{{ $nameFieldName }}"> <input name="{{ $validFromFieldName }}" type="text" value="{{ $encryptedValidFrom }}"> </div> @endif
触发事件
每当检测到垃圾邮件时,都会触发Spatie\Honeypot\Events\SpamDetectedEvent
事件。它将$request
作为一个公共属性。
测试
composer test
更改日志
有关最近更改的更多信息,请参阅更改日志。
替代方案
如果您需要更强的垃圾邮件保护,请考虑使用Google ReCaptcha或Akismet。
贡献
有关详细信息,请参阅贡献。
安全
如果您发现了关于安全性的错误,请通过security@spatie.be发送邮件,而不是使用问题跟踪器。
鸣谢
此包受到了Maksim Surguy的Honeypot包的启发。
许可证
MIT许可证(MIT)。有关更多信息,请参阅许可证文件。