Reputation: 321
How to integrate laravel throttle if I did not use the default LoginController given by laravel?
here's my controller:
use AuthenticatesUsers;
//function for login
public function login(Request $requests){
$username = $requests->username;
$password = $requests->password;
/**to login using email or username**/
if(filter_var($username, FILTER_VALIDATE_EMAIL)) {
Auth::attempt(['email' => $username, 'password' => $password]);
} else {
Auth::attempt(['username' => $username, 'password' => $password]);
}
if(Auth::check()){
if(Auth::user()->type_user == 0){
return view('users.dashboard');
}
else{
return view('admin.dashboard');
}
}
else{
return Redirect::back()->withInput()->withErrors(['message'=>$login_error],'login');
}
}
I want to limit the failed logins but I can't seem to make it work using my own controller. Can you guys help me please?
Upvotes: 16
Views: 21872
Reputation: 325
To Implement Rate Limiting in Laravel 11 Without Kernel.php or RouteServiceProvider.php
Since Laravel 11 removes Kernel.php and RouteServiceProvider.php, you can define rate limits directly in routes/web.php using RateLimiter::for().
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Route;
use Illuminate\Cache\RateLimiting\Limit;
RateLimiter::for('web', fn($request) => Limit::perMinute(100)->by($request->ip()));
Route::middleware('throttle:web')->group(function () {
Route::get('/login', [AuthController::class, 'login'])->name('login');
});
This limits requests to 100 per minute per IP. Use throttle: in your routes. No need to modify bootstrap/app.php. 🚀
Upvotes: 0
Reputation: 72
Route::post('login', ['before' => 'throttle:2,60', 'uses' => 'YourLoginController@Login']);
Upvotes: 1
Reputation: 1267
Try adding throttling to your controller's constructor, like so:
/**
* Create a new login controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('throttle:3,1')->only('login');
}
Unfortunately, the Laravel docs don't say much about throttling: https://laravel.com/docs/6.x/authentication#login-throttling
However, the 3,1
part of the string corresponds to a maximum of 3 tries with a decay time of 1 minute.
throttle
could be defined in /project-root/laravel/app/Http/Kernel.php
in the routeMiddleware
array like so:
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
.
The Laravel documentation explains this method here: https://laravel.com/docs/6.x/middleware#assigning-middleware-to-routes
Upvotes: 6
Reputation: 187
use Trait ThrottlesLogins present in Illuminate\Foundation\Auth and override the 2 functions as mentioned below. I have tested it on Laravel 5.6 and working fine.
public function maxAttempts()
{
//Lock out on 5th Login Attempt
return 5;
}
public function decayMinutes()
{
//Lock for 1 minute
return 1;
}
Upvotes: 4
Reputation: 368
Although, this answer is very late, but here is , what i did, and it worked. I hope it helps you too. I am using laravel 5.2.
<?php
namespace App\Http\Controllers;
use App\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\MessageBag;
use Cookie;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;
class UserController extends Controller
{
/** Add This line on top */
use AuthenticatesAndRegistersUsers,ThrottlesLogins;
/** This way, you can control the throttling */
protected $maxLoginAttempts=3;
protected $lockoutTime=300;
public function postUserSignIn(Request $request)
{
/** This line should be in the start of method */
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
/** Validate the input */
$validation = $this->validate($request,[
'email' => 'required|email',
'password' => 'required|min:4'
]);
/** Validation is done, now login user */
//else to user profile
$check = Auth::attempt(['email' => $request['email'],'password' => $request['password']]);
if($check){
$user = Auth::user();
/** Since Authentication is done, Use it here */
$this->clearLoginAttempts($request);
if ($user->role == 1 || $user->role == 2){
if(Session::has('cart')){
return redirect()->route('cart');
}
return redirect()->intended();
}elseif($user->role == 99) {
return redirect()->route('dashboard');
}
}else{
/** Authentication Failed */
$this->incrementLoginAttempts($request);
$errors = new MessageBag(['password' => ['Email and/or Password is invalid']]);
return redirect()->back()->withErrors($errors);
}
}
}
Upvotes: 2
Reputation: 789
add the following code inside your method. make it the first thing
// If the class is using the ThrottlesLogins trait, we can automatically throttle
// the login attempts for this application. We'll key this by the username and
// the IP address of the client making these requests into this application.
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}
now add the following code where log in fails. this will increment the failed attempt count.
$this->incrementLoginAttempts($request);
on successful login, add the following code so it resets.
$this->clearLoginAttempts($request);
Upvotes: 11
Reputation: 1
try my version:
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class LoginController extends Controller{
use AuthenticatesUsers;
public function login(Request $request){
if($this->hasTooManyLoginAttempts($request)){
$this->fireLockoutEvent($request);
return $this->sendLockoutResponse($request);
}else{
if (Auth::attempt(['username' => $request->login_username, 'password' => $request->login_password])) {
session()->put(['username'=>Auth::user()->username,'userid'=>Auth::user()->id]);
return redirect()->intended('anydashboard');
}else{
$this->incrementLoginAttempts($request);
//my '/' path is the login page, with customized response msg...
return redirect('/')->with(['illegal'=>'Login failed, please try again!'])->withInput($request->except('password'));
}
}
}
}
in order to use Eloquent Model Auth (which is default), your AUTH_MODEL should implements AuthenticatableContract, so double check your model:
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model implements AuthenticatableContract,CanResetPasswordContract
{
use Authenticatable, CanResetPassword;
//protected $fillable = [];
...
}
Upvotes: 0
Reputation: 72
if ($this->hasTooManyLoginAttempts($request)) {
$this->fireLockoutEvent($request);
return redirect()->route('login')->with('alert-warning', 'Too many login attempts');
}
protected function hasTooManyLoginAttempts(Request $request)
{
$maxLoginAttempts = 3;
$lockoutTime = 1; // In minutes
return $this->limiter()->tooManyAttempts(
$this->throttleKey($request), $maxLoginAttempts, $lockoutTime
);
}
Upvotes: 0