Laravel:在自定义登录中集成 Throttle

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/45180537/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 16:19:27  来源:igfitidea点击:

Laravel: Integrating Throttle in Custom Login

phplaravelvalidationlaravel-5.4throttling

提问by JaneTho

How to integrate laravel throttle if I did not use the default LoginController given by laravel?

如果我没有使用 laravel 提供的默认 LoginController,如何集成 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?

我想限制失败的登录,但我似乎无法使用我自己的控制器使其工作。你们能帮我吗?

回答by w1n78

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);

回答by j3py

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

不幸的是,Laravel 文档并没有对节流说太多:https://laravel.com/docs/6.x/authentication#login-throttling

However, the 3,1part of the string corresponds to a maximum of 3 tries with a decay time of 1 minute.

但是,3,1字符串的部分对应于最多 3 次尝试,衰减时间为 1 分钟。

throttlecould be defined in /project-root/laravel/app/Http/Kernel.phpin the routeMiddlewarearray 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

throttle可被定义在/project-root/laravel/app/Http/Kernel.php所述的routeMiddleware阵列,如下所示:
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,。Laravel 文档在这里解释了这种方法:https://laravel.com/docs/6.x/middleware#assigning-middleware-to-routes

回答by ferdousulhaque

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.

使用 Illuminate\Foundation\Auth 中的 Trait ThrottlesLogins 并覆盖下面提到的 2 个函数。我已经在 Laravel 5.6 上测试过它并且工作正常。

public function maxAttempts()
{
    //Lock out on 5th Login Attempt
    return 5;
}

public function decayMinutes()
{
    //Lock for 1 minute
    return 1;
}

回答by Ali Jibran

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.

虽然,这个答案已经很晚了,但这是我所做的,并且奏效了。我希望它也能帮助你。我正在使用 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);
    }

}

}

}

回答by Bikram Maharjan

Route::post('login', ['before' => 'throttle:2,60', 'uses' => 'YourLoginController@Login']);

回答by Bikram Maharjan

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
   );
}

回答by Shuo Wang

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:

为了使用 Eloquent Model Auth(默认),你的 AUTH_MODEL 应该实现 AuthenticatableContract,所以仔细检查你的模型:

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 = [];
...
}