Created
October 29, 2019 16:02
-
-
Save stevebauman/48ef5c189e8a62a799e70ad043067631 to your computer and use it in GitHub Desktop.
A Laravel validation rule for throttling form requests.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Http\Requests; | |
use App\Rules\Throttle; | |
use Illuminate\Foundation\Http\FormRequest; | |
class SubmissionFormRequest extends FormRequest | |
{ | |
/** | |
* Get the validation rules that apply to the request. | |
* | |
* @return array | |
*/ | |
public function rules() | |
{ | |
return [ | |
'my-field' => [ | |
'required', | |
'max:250', | |
new Throttle('submission', $maxAttempts = 5, $decayInMinutes = 10) | |
], | |
]; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace App\Rules; | |
use Illuminate\Http\Request; | |
use Illuminate\Cache\RateLimiter; | |
use Illuminate\Contracts\Validation\Rule; | |
class Throttle implements Rule | |
{ | |
/** | |
* The throttle key. | |
* | |
* @var string | |
*/ | |
protected $key = 'validation'; | |
/** | |
* The maximum number of attempts a user can perform. | |
* | |
* @var int | |
*/ | |
protected $maxAttempts = 5; | |
/** | |
* The amount of minutes to restrict the requests by. | |
* | |
* @var int | |
*/ | |
protected $decayInMinutes = 10; | |
/** | |
* Create a new rule instance. | |
* | |
* @param string $key | |
* @param int $maxAttempts | |
* @param int $decayInMinutes | |
* | |
* @return void | |
*/ | |
public function __construct($key = 'validation', $maxAttempts = 5, $decayInMinutes = 10) | |
{ | |
$this->key = $key; | |
$this->maxAttempts = $maxAttempts; | |
$this->decayInMinutes = $decayInMinutes; | |
} | |
/** | |
* Determine if the validation rule passes. | |
* | |
* @param string $attribute | |
* @param mixed $value | |
* | |
* @return bool | |
*/ | |
public function passes($attribute, $value) | |
{ | |
if ($this->hasTooManyAttempts()) { | |
return false; | |
} | |
$this->incrementAttempts(); | |
return true; | |
} | |
/** | |
* Get the validation error message. | |
* | |
* @return string | |
*/ | |
public function message() | |
{ | |
return __('Too many attempts. Please try again later.'); | |
} | |
/** | |
* Determine if the user has too many failed login attempts. | |
* | |
* @return bool | |
*/ | |
protected function hasTooManyAttempts() | |
{ | |
return $this->limiter()->tooManyAttempts( | |
$this->throttleKey(), $this->maxAttempts | |
); | |
} | |
/** | |
* Increment the login attempts for the user. | |
* | |
* @return void | |
*/ | |
protected function incrementAttempts() | |
{ | |
$this->limiter()->hit( | |
$this->throttleKey(), $this->decayInMinutes | |
); | |
} | |
/** | |
* Get the throttle key for the given request. | |
* | |
* @return string | |
*/ | |
protected function throttleKey() | |
{ | |
return $this->key . '|' . $this->request()->ip(); | |
} | |
/** | |
* Get the rate limiter instance. | |
* | |
* @return \Illuminate\Cache\RateLimiter | |
*/ | |
protected function limiter() | |
{ | |
return app(RateLimiter::class); | |
} | |
/** | |
* Get the current HTTP request. | |
* | |
* @return \Illuminate\Http\Request | |
*/ | |
protected function request() | |
{ | |
return app(Request::class); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thank you for this!