Banhammer for Laravel offers a very simple way to ban any Model by ID and by IP. It also allows to block requests by IP addresses.
Banned models can have an expiration date and will be automatically unbanned using the Scheduler.
- Introduction
- Version Compatibility
- Installation
- Usage
- UUIDs
- Upgrading To 2.0 from 1.x
- Testing
- Changelog
- Roadmap / Todo
- Contributing
- Security Vulnerabilities
- Credits
- License
Laravel | Banhammer |
---|---|
^9.0 | 1.x, 2.x |
^10.0 | 1.x, 2.x |
^11.0 | 1.x, 2.x |
You can install the package via composer:
composer require mchev/banhammer
Then publish and run the migrations with:
To use UUIDs see UUIDs
php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations"
php artisan migrate
You can publish the config file with:
php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="config"
It is possible to define the table name, the model and the fallback_url in the config/ban.php
file.
To make a model bannable, add the Mchev\Banhammer\Traits\Bannable
trait to the model:
<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Mchev\Banhammer\Traits\Bannable;
class User extends Authenticatable
{
use Bannable;
}
You can add the Bannable trait on as many models as you want (Team, Group, User, etc.).
Simple ban
$user->ban();
Without the expired_at attribute specified, the user will be banned forever.
IP Ban
$user->ban([
'ip' => $user->ip,
]);
Full
All attributes are optional
$model->ban([
'created_by_type' => 'App\Models\User',
'created_by_id' => 1,
'comment' => "You've been evil",
'ip' => "8.8.8.8",
'expired_at' => Carbon::now()->addDays(7),
'metas' => [
'route' => request()->route()->getName(),
'user_agent' => request()->header('user-agent')
]
]);
Shorthand
$user->banUntil('2 days');
Check if model is banned.
You can create custom middlewares using these methods.
$model->isBanned();
$model->isNotBanned();
List model bans
// All model bans
$bans = $model->bans()->get();
// Expired bans
$expired = $model->bans()->expired()->get();
// Not expired and permanent bans
$notExpired = $model->bans()->notExpired()->get();
Filters
$bannedTeams = Team::banned()->get();
$notBannedTeams = Team::notBanned()->get();
Unban
$user->unban();
Ban IPs
use Mchev\Banhammer\IP;
IP::ban("8.8.8.8");
IP::ban(["8.8.8.8", "4.4.4.4"]);
// Ban IP with expiration date
IP::ban("8.8.8.8", [], now()->addMinutes(10));
// Full
IP::ban(
"8.8.8.8",
[
"MetaKey1" => "MetaValue1",
"MetaKey2" => "MetaValue2",
],
now()->addMinutes(10)
);
Unban IPs
use Mchev\Banhammer\IP;
IP::unban("8.8.8.8");
IP::unban(["8.8.8.8", "4.4.4.4"]);
List all banned IPs
use Mchev\Banhammer\IP;
$ips = IP::banned()->get(); // Collection
$ips = IP::banned()->pluck('ip')->toArray(); // Array
Ban IP with metas
use Mchev\Banhammer\IP;
IP::ban("8.8.8.8", [
'route' => request()->route()->getName(),
'user_agent' => request()->header('user-agent')
]);
Metas usage
$ban->setMeta('username', 'Jane');
$ban->getMeta('username'); // Jane
$ban->hasMeta('username'); // boolean
$ban->forgetMeta('username');
Filtering by Meta
IP::banned()->whereMeta('username', 'Jane')->get();
// OR
$users->bans()->whereMeta('username', 'Jane')->get();
// OR
$users->whereBansMeta('username', 'Jane')->get();
To enhance the security of your application, you can restrict access from specific countries by enabling the country-blocking feature in the configuration file. Follow these simple steps:
-
Open your Banhammer configuration file (config/ban.php).
-
Set the 'block_by_country' configuration option to true to enable country-based blocking.
'block_by_country' => true,
- Specify the list of countries you want to block by adding their country codes to the 'blocked_countries' array.
'blocked_countries' => ['FR', 'ES'],
By configuring these settings, you effectively block access to your application for users originating from the specified countries. This helps improve the security and integrity of your system by preventing unwanted traffic from regions you've identified as potential risks.
Important Notice: The Banhammer package utilizes the free version of ip-api.com for geolocation data. Keep in mind that their endpoints have a rate limit of 45 HTTP requests per minute from a single IP address. If you exceed this limit, your requests will be throttled, and you may receive a 429 HTTP status code until your rate limit window is reset.
Developer Note: While Banhammer currently relies on the free version of ip-api.com for geolocation data, I'm open to exploring better alternatives. If you have suggestions for a more robust or efficient solution, or if you'd like to contribute improvements, please feel free to open an issue or submit a pull request.
To prevent banned users from accessing certain parts of your application, simply add the auth.banned
middleware on the concerned routes.
Route::middleware(['auth.banned'])->group(function () {
// ...
});
To prevent banned ips from accessing certain parts of your application, simply add the ip.banned
middleware on the concerned routes.
Route::middleware(['ip.banned'])->group(function () {
// ...
});
To block and logout banned Users or IP, add the logout.banned
middleware:
Route::middleware(['logout.banned'])->group(function () {
// ...
});
If you use the
logout.banned
middleware, it is not necessary to cumulate the other middlewares.
If you want to block IPs on every HTTP request of your application, list
Mchev\Banhammer\Middleware\IPBanned
in the$middleware
property of yourapp/Http/Kernel.php
class.
⚠ IMPORTANT
In order to be able to automatically delete expired bans, you must have a cron job set up on your server to run the Laravel Scheduled Jobs
If entity is banned Mchev\Banhammer\Events\ModelWasBanned
event is fired.
Is entity is unbanned Mchev\Banhammer\Events\ModelWasUnbanned
event is fired.
To manually unban expired bans :
use Mchev\Banhammer\Banhammer;
Banhammer::unbanExpired();
Or you can use the command:
php artisan banhammer:unban
To permanently delete all the expired bans :
use Mchev\Banhammer\Banhammer;
Banhammer::clear();
Or you can use the command:
php artisan banhammer:clear
To use UUIDs make sure you publish and edit the migration files.
php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="migrations"
- $table->id();
+ $table->uuid('id');
You will then need to make a model that extends Mchev\Banhammer\Models\Ban
:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
use Mchev\Banhammer\Models\Ban as BanhammerBan;
class Ban extends BanhammerBan
{
use HasUuids;
}
Although most of the methods needed are already available from the base model, you can add any additional methods here.
Finally update the published ban.php
config file to load the model you have created:
/*
|--------------------------------------------------------------------------
| Model Name
|--------------------------------------------------------------------------
|
| Specify the model which you want to use as your Ban model.
|
*/
- 'model' => \Mchev\Banhammer\Models\Ban::class,
+ 'model' => \App\Models\YouBanClass::class,
To upgrade to Banhammer version 2.0, follow these simple steps:
- Update the package version in your application's
composer.json
file:
"require": {
"mchev/banhammer": "^2.0"
}
- Run the following command in your terminal:
composer update mchev/banhammer
-
Update the configuration
- Update the configuration
- Backup your previous configuration file located at
config/ban.php
. - Force republish the new configuration using the command:
php artisan vendor:publish --provider="Mchev\Banhammer\BanhammerServiceProvider" --tag="config" --force
- Review the new configuration file and make any necessary edits.
- Backup your previous configuration file located at
- Update the configuration
composer test
Please see CHANGELOG for more information on what has changed recently.
- Laravel pulse card (ips banned, block by country enabled, etc.).
- Block by country feature
To encourage active collaboration, Banhammer strongly encourages pull requests, not just bug reports. Pull requests will only be reviewed when marked as "ready for review" (not in the "draft" state) and all tests for new features are passing. Lingering, non-active pull requests left in the "draft" state will be closed after a few days.
However, if you file a bug report, your issue should contain a title and a clear description of the issue. You should also include as much relevant information as possible and a code sample that demonstrates the issue. The goal of a bug report is to make it easy for yourself - and others - to replicate the bug and develop a fix.
Remember, bug reports are created in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the bug report will automatically see any activity or that others will jump to fix it.
Please review our security policy on how to report security vulnerabilities.
- Inspired by laravel-ban from cybercog
The MIT License (MIT). Please see License File for more information.