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

Posted

技术标签:

【中文标题】Laravel:在自定义登录中集成 Throttle【英文标题】:Laravel: Integrating Throttle in Custom Login 【发布时间】:2017-12-24 03:12:27 【问题描述】:

如果我没有使用 laravel 提供的默认 LoginController,如何集成 laravel 油门?

这是我的控制器:

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

    
  

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

【问题讨论】:

- 使用油门特征作为“使用油门登录;”在您的登录控制器中 仍然无法正常工作。 :( 【参考方案1】:
Route::post('login', ['before' => 'throttle:2,60', 'uses' => 'YourLoginController@Login']);

【讨论】:

油门应该在验证之后。也没有办法向用户发送验证响应消息。【参考方案2】:

尝试向控制器的构造函数添加限制,如下所示:

/**
 * Create a new login controller instance.
 *
 * @return void
 */
public function __construct()

    $this->middleware('throttle:3,1')->only('login');

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

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

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

【讨论】:

【参考方案3】:

使用 Illuminate\Foundation\Auth 中的 Trait ThrottleLogins 并覆盖下面提到的 2 个函数。我已经在 Laravel 5.6 上对其进行了测试并且工作正常。

public function maxAttempts()

    //Lock out on 5th Login Attempt
    return 5;


public function decayMinutes()

    //Lock for 1 minute
    return 1;

【讨论】:

除了覆盖函数之外,您还可以使用属性:protected $maxAttempts = 3; protected $decayMinutes = 1;(如果需要,可以是受保护的或公开的)【参考方案4】:

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


【讨论】:

【参考方案5】:

在您的方法中添加以下代码。把它放在第一位

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

现在在登录失败的地方添加以下代码。这将增加失败的尝试次数。

$this->incrementLoginAttempts($request);

登录成功后,添加以下代码使其重置。

$this->clearLoginAttempts($request);

【讨论】:

如何通过电子邮件而不是用户名输入? 用你想要的键覆盖Illuminate\Foundation\Auth\ThrottlesLogins::throttleKey()方法。【参考方案6】:

试试我的版本:

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


为了使用 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 = [];
...

【讨论】:

也不认为它有效。我还尝试调试$this-&gt;incrementLoginAttempts($request); 以查看是否在增加,但结果只是null 看看@你的模型,就像上面一样。【参考方案7】:
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
   );

【讨论】:

对不起,我应该把这个放在哪里? 在你的控制器中 我收到一条错误消息:(1/1) BadMethodCallException 方法 [用户名] 不存在。在 Controller.php 中(第 82 行) $this-&gt;username()AuthenticatesUsers 特征中的一个方法。您可以在vendor/laravel/ui/auth-backend/AuthenticatesUsers.php 浏览该文件。如果您不覆盖它,它将返回email。如果您不在身份验证控制器中use AuthenticatesUsers;,您将收到该错误。

以上是关于Laravel:在自定义登录中集成 Throttle的主要内容,如果未能解决你的问题,请参考以下文章

如何在 laravel 中集成 paypal

在 laravel 中集成我的管理面板仪表板后出现错误消息

在 laravel 5 中集成 hybrid_auth

在 Laravel 5 中集成七牛云存储实现云存储功能

没有在自定义类下拉列表中显示 EDStarRating?

在laravel5.8中集成swoole组件