前言
- 因為在網上沒有看到一篇完整的講述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 協議》,轉載必須註明作者和本文連結