Laravel 5.3 使用內置的 Auth 組件實現多用戶認證功能
https://blog.csdn.net/kevinbai_cn/article/details/54341779
概述
在開發中,我們經常會遇到多種類型的用戶的認證問題,比如後臺的管理員和前臺的普通用戶。Laravel 5.3 內置的 Auth 組件已經能很好的滿足這項需求,下面大概記錄下使用方法。
另外,後臺頁面常常需要登錄才能訪問,為了完成類似的功能,大家一般都習慣創建新的中間件來實現。但是 Auth 組件已經存在類似的中間件,我們可以在已有的基礎上進行完善,具體請看 後臺認證
-> 登陸才能訪問後臺的功能的一種實現方法
。
註意:這裏我們只考慮管理員和普通用戶存放在不同的表中的情況
創建項目
創建項目 E:\PhpStormProjects>composer create-project --prefer-dist laravel/laravel blog
進入項目 E:\PhpStormProjects>cd blog
運行項目 E:\PhpStormProjects\blog>php arstisan serve
看看效果 瀏覽器訪問http://localhost:8000
項目配置
數據庫配置 .env
中配置 DB 相關選項即可
前臺認證
數據庫遷移 E:\PhpStormProjects\blog>php artisan migrate
生成 Auth E:\PhpStormProjects\blog>php artisan make:auth
該命令應該在新安裝的應用下使用,它會生成 layout 布局視圖,註冊和登錄視圖,以及所有的認證路由,同時生成 HomeController ,用來處理登錄成功後會跳轉到該控制器下的請求。
瀏覽器訪問 http://localhost:8000
我們看到右上角多了 LOGIN 和 REGISTER 的鏈接,我們可以試著註冊和登陸。
至此,前臺認證完成。
後臺認證
後臺首頁顯示
生成後臺首頁控制器 E:\PhpStormProjects\blog>php artisan make:controller Admin/IndexController
建立後臺首頁的視圖 resources/views/admin/index.blade.php
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首頁 | 後臺系統</title>
</head>
<body>
<h3>首頁</h3>
</body>
</html>
後臺首頁控制器 app/Http/Controllers/Admin/IndexController.php
添加方法
public function index()
{
return view(‘admin/index‘);
}
路由文件 routes/web.php
添加路由組
Route::group([‘prefix‘ => ‘admin‘], function () {
Route::get(‘/‘, ‘Admin\IndexController@index‘);
});
瀏覽器訪問 http://localhost:8000/admin
可看到後臺首頁
後臺首頁顯示完成
管理員數據表生成、數據表模型建立以及數據表填充
生成管理員數據表遷移文件 E:\PhpStormProjects\blog>php artisan make:migration create_administrators_table
修改 database/migrations/*_create_administrators_table.php
中的 up() 與 down() 方法
public function up()
{
Schema::create(‘administrators‘, function (Blueprint $table) {
$table->increments(‘id‘);
$table->string(‘name‘);
$table->string(‘email‘)->unique();
$table->string(‘password‘);
$table->rememberToken();
$table->timestamps();
});
}
public function down()
{
Schema::drop(‘administrators‘);
}
生成數據表 E:\PhpStormProjects\blog>php artisan migrate
至此,數據表建立
生成數據表模型 E:\PhpStormProjects\blog>php artisan make:model Models/Administrator
修改 app/Models/Administrator.php
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class Administrator extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
‘name‘, ‘email‘, ‘password‘,
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
‘password‘, ‘remember_token‘,
];
}
提示:該模型根據app/User.php
修改
至此數據表模型建立完成
生成數據表填充文件 E:\PhpStormProjects\blog>php artisan make:seeder AdministratorsTableSeeder
database/factories/ModelFactory.php
中添加
$factory->define(App\Models\Administrator::class, function (Faker\Generator $faker) {
static $password;
return [
‘name‘ => $faker->name,
‘email‘ => $faker->unique()->safeEmail,
‘password‘ => $password ?: $password = bcrypt(‘secret‘),
‘remember_token‘ => str_random(10),
];
});
修改 database/seeds/AdministratorsTableSeeder.php
中的 run() 方法
public function run()
{
factory(App\Models\Administrator::class, 3)->create([
‘password‘ => bcrypt(‘040313‘),
]);
}
修改 database/seeds/DatabaseSeeder.php
中的 run() 方法
public function run()
{
$this->call(AdministratorsTableSeeder::class);
}
數據表填充 E:\PhpStormProjects\blog>php artisan db:seed
至此,數據表填充完成,在 administrators 中可看到 3 條樣例數據
管理員登陸頁面顯示
新建 app/Http/Controllers/Admin/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
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‘;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware(‘guest‘, [‘except‘ => ‘logout‘]);
}
/**
* 重寫 Show the application‘s login form.
*
* @return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view(‘admin/auth/login‘);
}
}
提示:該控制器內容根據 app/Http/Controllers/Auth/LoginController.php
修改
新建 resources/views/admin/Auth/login.blade.php
,復制 resources/views/auth/login.blade.php
的內容到這個文件即可
註意:不要忘了修改登陸表單的 action
地址為 {{ url(‘/admin/login‘) }}
修改路由組
Route::group([‘prefix‘ => ‘admin‘], function () {
Route::get(‘login‘, ‘Admin\Auth\LoginController@showLoginForm‘);
Route::get(‘/‘, ‘Admin\IndexController@index‘);
});
至此,後臺登陸頁面顯示完成。訪問 http://localhost:8000/admin/login
可看到對應頁面
管理員認證
修改 config/auth.php
,在鍵為 guards
和 providers
的數組中添加管理員相關信息
‘guards‘ => [
‘web‘ => [
‘driver‘ => ‘session‘,
‘provider‘ => ‘users‘,
],
‘api‘ => [
‘driver‘ => ‘token‘,
‘provider‘ => ‘users‘,
],
‘admin‘ => [
‘driver‘ => ‘session‘,
‘provider‘ => ‘administrators‘,
],
],
‘providers‘ => [
‘users‘ => [
‘driver‘ => ‘eloquent‘,
‘model‘ => App\User::class,
],
// ‘users‘ => [
// ‘driver‘ => ‘database‘,
// ‘table‘ => ‘users‘,
// ],
‘administrators‘ => [
‘driver‘ => ‘eloquent‘,
‘model‘ => App\Models\Administrator::class,
],
],
修改 app/Http/Controllers/Admin/Auth/LoginController.php
<?php
namespace App\Http\Controllers\Admin\Auth;
use App\Http\Controllers\Controller;
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‘;
/**
* Create a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware(‘guest:admin‘, [‘except‘ => ‘logout‘]);
}
/**
* 重寫 Show the application‘s login form.
*
* @return \Illuminate\Http\Response
*/
public function showLoginForm()
{
return view(‘admin/auth/login‘);
}
/**
* 重寫 Get the guard to be used during authentication.
*
* @return \Illuminate\Contracts\Auth\StatefulGuard
*/
protected function guard()
{
return \Auth::guard(‘admin‘);
}
/**
* 重寫 Log the user out of the application.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function logout(Request $request)
{
$this->guard()->logout();
$request->session()->flush();
$request->session()->regenerate();
return redirect(‘/admin/login‘);
}
}
app/Http/Middleware/RedirectIfAuthenticated.php
即 guest
中間件。它的作用是當請求者請求登陸時,如果已登錄則將其跳轉到合適頁面。如果請求的是後臺登陸頁面且已登錄的話,我們應將其跳轉到後臺首頁,而不是默認的前臺首頁。修改其中的 handle() 方法
public function handle($request, Closure $next, $guard = null)
{
if (Auth::guard($guard)->check()) {
$path = $guard? ‘/admin‘ : ‘/home‘;
return redirect($path);
}
return $next($request);
}
修改路由組
Route::group([‘prefix‘ => ‘admin‘], function () {
Route::get(‘login‘, ‘Admin\Auth\LoginController@showLoginForm‘);
Route::post(‘login‘, ‘Admin\Auth\LoginController@login‘);
Route::post(‘logout‘, ‘Admin\Auth\LoginController@logout‘);
Route::get(‘/‘, ‘Admin\IndexController@index‘);
});
順便在後臺首頁添加一個登出鏈接,修改 resources/views/admin/index.blade.php
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>首頁 | 後臺系統</title>
</head>
<body>
<h3>首頁</h3>
<p>
狀態:
@if(Auth::guard(‘admin‘)->check())
已登錄
<a href="#"
onclick="event.preventDefault();
document.getElementById(‘logout-form‘).submit();">
Logout
</a>
<form id="logout-form" action="{{ url(‘/admin/logout‘) }}" method="POST" style="display: none;">
{{ csrf_field() }}
</form>
@else
未登錄
@endif
</p>
</body>
</html>
至此,管理員認證(登入與登出)已基本完成。
註意:由於後臺很少需要註冊功能,所以這部分功能實現不在考慮範圍
登陸才能訪問後臺的功能的一種實現方法
目前的後臺認證中,如果管理員沒有登錄,他也能訪問後臺首頁,這顯然是有問題的。這裏,可以利用自帶的 Auth 系統的 vendor/laravel/framework/src/Illuminate/Auth/Middleware/Authenticate.php
這個中間件來實現。查看其中的 authenticate() 方法
protected function authenticate(array $guards)
{
if (empty($guards)) {
return $this->auth->authenticate();
}
foreach ($guards as $guard) {
if ($this->auth->guard($guard)->check()) {
return $this->auth->shouldUse($guard);
}
}
throw new AuthenticationException(‘Unauthenticated.‘, $guards);
}
如果管理員或者用戶沒有登錄,則會拋出認證異常。我們可以在 app/Exceptions/Handler.php
中處理這個異常,將登陸者轉到相應頁面。所以我們可以修改這個文件中的 unauthenticated() 方法
protected function unauthenticated($request, AuthenticationException $exception)
{
if ($request->expectsJson()) {
return response()->json([‘error‘ => ‘Unauthenticated.‘], 401);
}
if(in_array(‘admin‘, $exception->guards())) {
return redirect()->guest(‘/admin/login‘);
}
return redirect()->guest(‘login‘);
}
修改路由組
Route::group([‘prefix‘ => ‘admin‘], function () {
Route::get(‘login‘, ‘Admin\Auth\LoginController@showLoginForm‘);
Route::post(‘login‘, ‘Admin\Auth\LoginController@login‘);
Route::post(‘logout‘, ‘Admin\Auth\LoginController@logout‘);
Route::group([‘middleware‘ => ‘auth:admin‘], function () {
Route::get(‘/‘, ‘Admin\IndexController@index‘);
});
});
至此,後臺登陸才能訪問。
Laravel 5.3 使用內置的 Auth 組件實現多用戶認證功能