Laravel 5.3 自带多权限登录正确姿势
前言
- 因为在网上没有看到一篇完整的讲述5.3多权限登录验证的问题,而且以前我们是需要通过插件包来实现,现在5.3中可以直接用内部机制。所以抛砖引玉的讲一天的研究成果成文分享给大家。希望大家快乐学习,也同样乐于分享。
在正式开始之前,请确认已经熟悉对应的laravel-china翻译的官方文档:http://learnku.com/docs/laravel/5.3/authen...
1,建立模型
namespace App\Models;
use App\Models\Traits\AdminTrait;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Admin extends Authenticatable
{
use Notifiable;
use AdminTrait;
protected $table = "admins";
……
}
这里注意是extends Authenticatable,而非默认的model
修改config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'token',
'provider' => 'users',
],
'admin' => [
'driver' => 'session',
'provider' => 'admins',
],
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
],
// 'users' => [
// 'driver' => 'database',
// 'table' => 'users',
// ],
],
- 在guard数组里面规定了3套验证机制,分别是会话型的user 和 admin,这两种是需要我们进行登录验证的(一般采用中间件方式),另外一种就是前后端分离时会用到的api,这种一般都是通过指定过期的token进行临时性的会话,这也是为了后面控制器中使用guard做准备。同时注意providers中驱动模型采用eloquent方式,也就是数据模型驱动。
2,接下来建立控制器
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use Auth;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
class LoginController extends Controller
{
/*
|--------------------------------------------------------------------------
| Login Controller
|--------------------------------------------------------------------------
|
| This controller handles authenticating users for the application and
| redirecting them to your home screen. The controller uses a trait
| to conveniently provide its functionality to your applications.
|
*/
use AuthenticatesUsers;
/**
* Where to redirect users after login.
*
* @var string
*/
protected $redirectTo = '/admin/dashboard';
/**
* 如果是在地址栏中输入登录url,就需要先判断是否已经登录。
*
*/
public function getLogin()
{
if ($this->guard()->check()) {
return redirect()->route('admin.dashboard.index');
}
return view('admin.auth.login');
}
/**
* 采用post方法进行登录时采用的验证机制
*
*/
public function postLogin(Request $request)
{
$this->validate($request, [
$this->loginUsername() => 'required', 'password' => 'required',
]);
// $this->validateLogin($request);
// 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);
}
/////////////////////////////////////////////////////////////////
// 注意下面采用的是Auth::guard('admin’)验证方式。 //
////////////////////////////////////////////////////////////////
// if ($this->attemptLogin($request)) {
if (Auth::guard('admin') //也可以写成:$this->guard(),这样更利于代码的维护,原因自行分析。
->attempt(['email'=>$request->email, 'password'=>$request->password],
$request->has('remember'))) {
//if (Auth::attempt(['email'=>$request->email,'password'=>$request->password], $request->has('remember'))) {
return redirect()->route('admin.dashboard.index');
}
// If the login attempt was unsuccessful we will increment the number of attempts
// to login and redirect the user back to the login form. Of course, when this
// user surpasses their maximum number of attempts they will get locked out.
$this->incrementLoginAttempts($request);
return $this->sendFailedLoginResponse($request);
}
/**
* 可选择不同的字段作为校验和登录名用。
* 比如,你登录是采用用户名登录,这里就return 'name‘,如果你是想用email进行登录,就在这里返回email字符串
* 是不是非常方便?
*/
public function loginUsername()
{
return 'email';
}
protected function guard()
{
return Auth::guard('admin');
}
/**
* 退出登录,同时跳转到登录页面。
*
*/
public function getLogout(Request $request)
{
$this->guard()->logout();
return redirect()->route('admin.login');
}
}
- 5.1中是没有采用guard的,所以这里需要大家先看官方文档,再来看本文的原因所在。
- 被注释的验证代码是5.1中的验证方式,大家可以对比看看有哪些不同。
3,路由
3.1 配置Kernel.php
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'bindings',
],
'admin' => [
\App\Http\Middleware\AdminAuthenticate::class,
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
];
/**
* The application's route middleware.
*
* These middleware may be assigned to groups or used individually.
*
* @var array
*/
protected $routeMiddleware = [
'admin' => \App\Http\Middleware\AdminAuthenticate::class,
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
- 这里面的middlewareGroups里的admin中也必须加上各种必须中间件,不然在routes/admin.php中虽然加上了“admin”中间件,还是无法进入对应的方法中进行验证。其他组件也必须加上,不然cookies,sessions,CSRF 的功能就没有了。其中,
- web 一般是我们用于前端的各种操作进行处理;
- api 是进行无状态回话接口设计,方便前后端分离,或者其他站点授权访问机制;
- admin 主要是用于后台管理方面;
上面AdminAuthenticate.php具体内容:
<?php
namespace App\Http\Middleware;
use Auth;
use Closure;
class AdminAuthenticate
{
public function handle($request, Closure $next)
{
if (!Auth::guard('admin')->check()) {
return redirect()->route('admin.login');
}
return $next($request);
}
}
3.2 配置RouteServiceProvider.php
- 这里配置的目的是将不同用途的路由拆分到不同的文件中,同时采取不同的验证机制,便于合理组织我们的代码。
public function map()
{
$this->mapApiRoutes();
$this->mapWebRoutes();
$this->mapAdminRoutes();
}
protected function mapWebRoutes()
{
Route::group([
'middleware' => 'web',
'namespace' => $this->namespace,
], function ($router) {
require base_path('routes/web.php');
});
}
protected function mapApiRoutes()
{
Route::group([
'middleware' => 'api',
'namespace' => $this->namespace,
'prefix' => 'api',
], function ($router) {
require base_path('routes/api.php');
});
}
protected function mapAdminRoutes()
{
Route::group([
'namespace' => 'App\Http\Controllers\Admin',
'prefix' => 'admin',
'middleware' => 'web',
], function ($router) {
require base_path('routes/admin.php');
});
}
这里面特别要强调mapAdminRoutes方法,这里面的middleware千万不要写成admin了,不然会形成无限死循环的。始终会进入AdminAuthenticate.php中的验证方法出不去。
3.3 配置routes/admin.php
Route::get('login', 'LoginController@getLogin')->name('admin.login');
Route::post('login', 'LoginController@postLogin')->name('admin.post.login');
Route::get('logout', 'LoginController@getLogout')->name('admin.logout');
Route::group(['middleware' => 'admin', 'as' => 'admin.'], function () {
Route::get('/', 'HomeController@index');
Route::get('/dashboard', 'DashboardController@index')->name('dashboard.index');
}
重要的事情再次强调下:
- 上面Kernel中的middlewareGroups【admin】中也必须加上\App\Http\Middleware\AdminAuthenticate::class,,不然在routes/admin.php中虽然加上了“admin”中间件,还是无法进入对应的方法中进行验证。
2017.7.30
[TODO]
忘了写config下面的auth配置,晚上补上。
[DONE] 2017.7.30 10时补充完整。
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: