天天看點

Laravel 5.3 使用内置的 Auth 元件實作多使用者認證功能以及登陸才能通路背景的功能的一種實作方法概述建立項目項目配置前台認證背景認證測試環境

概述

在開發中,我們經常會遇到多種類型的使用者的認證問題,比如背景的管理者和前台的普通使用者。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\[email protected]');
});
           

浏覽器通路

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(),
    ];
});
           

修改

database/seeds/AdministratorsTableSeeder.php

中的 run() 方法

public function run()
{
    factory(App\Models\Administrator::class, )->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\[email protected]');

    Route::get('/', 'Admin\[email protected]');
});
           

至此,背景登陸頁面顯示完成。通路

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\[email protected]');
    Route::post('login', 'Admin\Auth\[email protected]');
    Route::post('logout', 'Admin\Auth\[email protected]');

    Route::get('/', 'Admin\[email protected]');
});
           

順便在背景首頁添加一個登對外連結接,修改

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())
            已登入&nbsp;
            <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.'], );
    }

    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\[email protected]');
    Route::post('login', 'Admin\Auth\[email protected]');
    Route::post('logout', 'Admin\Auth\[email protected]');

    Route::group(['middleware' => 'auth:admin'], function () {
        Route::get('/', 'Admin\[email protected]');
    });
});
           

至此,背景登陸才能通路。

測試環境

httpd--x64-vc11
php--Win32-VC11-x64
mysql--winx64