php
57 lines · 9 steps
Rate-limited login in Laravel
A login controller that validates credentials, throttles brute-force attempts, and hardens the session on success.
Explained by
highlit
1<?php
2
3namespace App\Http\Controllers\Auth;
4
5use App\Http\Controllers\Controller;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Auth;
8use Illuminate\Support\Facades\RateLimiter;
9use Illuminate\Support\Str;
10use Illuminate\Validation\ValidationException;
11
12class LoginController extends Controller
13{
14 public function store(Request $request)
15 {
16 $credentials = $request->validate([
17 'email' => ['required', 'email'],
18 'password' => ['required', 'string'],
19 ]);
20
21 $this->ensureIsNotRateLimited($request);
22
23 if (! Auth::attempt($credentials, $request->boolean('remember'))) {
24 RateLimiter::hit($this->throttleKey($request));
25
26 throw ValidationException::withMessages([
27 'email' => __('auth.failed'),
28 ]);
29 }
30
31 RateLimiter::clear($this->throttleKey($request));
32 $request->session()->regenerate();
33
34 return redirect()->intended('/dashboard');
35 }
36
37 protected function ensureIsNotRateLimited(Request $request): void
38 {
39 if (! RateLimiter::tooManyAttempts($this->throttleKey($request), 5)) {
40 return;
41 }
42
43 $seconds = RateLimiter::availableIn($this->throttleKey($request));
44
45 throw ValidationException::withMessages([
46 'email' => __('auth.throttle', [
47 'seconds' => $seconds,
48 'minutes' => ceil($seconds / 60),
49 ]),
50 ]);
51 }
52
53 protected function throttleKey(Request $request): string
54 {
55 return Str::transliterate(Str::lower($request->input('email')).'|'.$request->ip());
56 }
57}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Throttling login by email plus IP blunts brute-force attacks without locking out whole networks.
- 2Regenerating the session on successful login defends against session fixation.
- 3Returning identical validation errors for failed and throttled logins avoids leaking account state.
Related explainers
php
<?php class NameParser {
Parsing a full name into components in PHP
string-parsing
arrays
normalization
Intermediate
8 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
python
import time import uuid from django.utils.deprecation import MiddlewareMixin
Attaching per-request context in Django
middleware
request lifecycle
multi-tenancy
Intermediate
7 steps
php
<?php namespace App\Services;
How a password strength validator works in PHP
validation
regular-expressions
data-driven
Intermediate
8 steps
php
<?php namespace App\Services;
Building a cached daily leaderboard in Laravel
caching
aggregation
eager-loading
Intermediate
9 steps
rust
use chrono::{Duration, NaiveDate}; #[derive(Debug)] pub struct DateRange {
Parsing and iterating date ranges in Rust
error-handling
iterators
parsing
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/rate-limited-login-in-laravel-explained-php-b38b/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.