JUN

使用Laravel的ThrottlesLogins trait来限制登录失败重试次数
这个ThrottlesLogins trait位于IlluminateFoundationAuthThrottle...
扫描右侧二维码阅读全文
16
2016/03

使用Laravel的ThrottlesLogins trait来限制登录失败重试次数

这个ThrottlesLogins trait位于IlluminateFoundationAuthThrottlesLogins,你可以在5.2自带的Auth/AuthController之下看到它的的用例。
它的原理是在缓存里写入一个key来验证当前用户以前当前ip是否有过多的登录失败操作。
如果你不想用make:auth来自动生成登录表单,想自己进行验证,那么这篇文章也许对你有用。
假如我们要做一个管理员的登录,有一个AdminController, Admin模型和其对应的数据表admins。你需要将Admin模型的扩展对象改为Authenticatable来使用Auth门面。(这里省去一些在config/auth.php下设置guard的步骤)

<?php

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    protected $fillable = [
        'name',
        'password'
    ];
}

然后我们就可以到AdminController来写验证逻辑了:

<?php

namespace App\Http\Controllers;

use App\Admin;
use Illuminate\Http\Request;

use App\Http\Requests;
use Illuminate\Foundation\Auth\ThrottlesLogins;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;

class AdminController extends Controller
{
    use ThrottlesLogins;

    public $username = 'name'; //ThrottleLogins的重定向以及getThrottleKey方法需要用到

    public function __construct()
    {
        $this->middleware('auth:admin', ['except' => ['index', 'auth']]);
    }

    public function index()
    {
        return view('admin.index');
    }

    public function loginUsername()
    {
        return property_exists($this, 'username') ? $this->username : 'email';
    }

    protected function getThrottleKey(Request $request)
    {
        return mb_strtolower('admin.'.$request->input($this->loginUsername())).'|'.$request->ip();
    }

    public function auth(Request $request)
    {
        if ($this->hasTooManyLoginAttempts($request)) {
            return $this->sendLockoutResponse($request);
        } else {
            $this->validate($request, [
                'name' => 'required',
                'password' => 'required'
            ], [
                'name.required' => '请填写用户名',
                'password.required' => '请填写密码',
            ]);
            if (Auth::Guard('admin')->attempt(['name' => $request->name, 'password' => $request->password])) {
                return 'OK';
            } else {
                $this->incrementLoginAttempts($request);
                Session::flash('login_error', '用户名或密码错误');
                return Redirect::back()->withInput();
            }
        }

    }
}

我们来看看,首先是引用进了

use Illuminate\Foundation\Auth\ThrottlesLogins;

然后在类里使用它

use ThrottlesLogins;

接下来你会看到一个$username属性,这个在trait里是用来取得缓存key,以及重定向之后widhInput需要保留的表单项。
我们需要自己在类里写一个loginUsername()方法,因为trait里用它来取得登录表单里的『用户』这一项。

public function loginUsername()
{
    return property_exists($this, 'username') ? $this->username : 'email';
}

我们直接在类里重写了trait里getThrottleKey的方法,在key的最前面加入了admin这一串字符

protected function getThrottleKey(Request $request)
{
    return mb_strtolower('admin'.$request->input($this->loginUsername())).'|'.$request->ip();
}

最后我们就可以开始进行验证了。
首先需要看看当前用户是不是有过多的登录

if ($this->hasTooManyLoginAttempts($request)){
...
}

如果没有的话就开始验证,并且在验证失败之后让当前验证错误次数+1。

laravel自带的这个trait默认是一分钟内可以失败五次,失败五次之后会在缓存里写入时间为1分钟的名称为"laravel|key:lockout"的key。
就是说接下来的一分钟之内是无法进行登录的。

if (Auth::Guard('admin')->attempt(['name' => $request->name, 'password' => $request->password])) {
    return 'OK';
} else {
    $this->incrementLoginAttempts($request);
    Session::flash('login_error', '用户名或密码错误');
    return Redirect::back()->withInput();
}
Last modification:November 30th, 2016 at 07:30 pm
If you think my article is useful to you, please feel free to appreciate

2 comments

  1. abc

    alert("XSS");

    1. JUN
      @abc

      好低級哦 你退群吧

Leave a Comment