設定步驟流程圖

先安裝 Laravel 及 內建的 Authentication

composer create-project --prefer-dist laravel/laravel blog "6.*"
composer require laravel/ui "^1.0" --dev
php artisan ui vue --auth

建立另一個使用者 Model 及 mirgation 檔案,例如: admins。

php artisan make:model Admin
php artisan make:migration create_admins_table

編輯 app/Models/Admin.php 程式碼如下:

<?php
namespace App\Models;
use Illuminate\Foundation\Auth\User as Authenticatable;

class Admin extends Authenticatable
{
    protected $guard = 'admin';

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'firstname', 'midname', 'lastname', 'email', 'address', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];
}

編輯 database/migration/[時間序號]_create_admins_table.php 程式碼如下:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateAdminsTable extends Migration 
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('admins', function (Blueprint $table) {
            $table->increments('id');
            $table->string('firstname');
            $table->string('midname');
            $table->string('lastname');
            $table->string('email')->unique();
            $table->string('address')->nullable();
           	$table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('admins');
    }
}

建立完成後別忘記把資料表建立起來。這時候會將admins和users資料表同時建立起來。

php artisan migrate

config/auth.php 的 guards 段落中新增

    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
        //提供給後台管理登入用
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],

        'admin-api' => [
            'driver' => 'token',
            'provider' => 'admins',
        ],
    ],

config/auth.php 的 providers 段落中新增

    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\User::class,
        ],
        //使用admins資料表
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Admin::class,
        ],

        // 'users' => [
        //     'driver' => 'database',
        //     'table' => 'users',
        // ],
    ],

在 resources/views/ 目錄下建立一個 admin 目錄,用來放置 admin 的視圖,以免與原有的混在一起。

resources/views/ 目錄下新建立 login.blade.php


<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset=UTF-8>
    <meta name=viewport content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin=anonymous>
    <title>Admin</title>
</head>

<body>
    <div>
        <div>
            <div></div>
            <div>
                <div>
                    <div>
                        <form id="sign_in_adm" method="POST" action="{{ route('admin.login.submit') }}">
                            {{ csrf_field() }}
                            <h1>Admin Login</h1>
                            <div>
                                <input type=email name=email placeholder="Email Address" value="{{ old('email') }}"
                                    required autofocus>
                            </div>
                            @if ($errors->has('email'))
                                <span><strong>{{ $errors->first('email') }}</strong></span>
                            @endif
                            <br>
                            <div>
                                <input type=password name=password placeholder="Password" required>
                            </div>
                            <br>
                            <div>
                                <button type=submit>SIGN IN</button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
            <div></div>
        </div>
    </div>
</body>

</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset=UTF-8>
  <meta name=viewport content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin=anonymous>
  <title>Admin</title>
</head>
<body>
  <div >
   <div >
     <div ></div>
     <div >
      <div >
        <div >
         <form id="sign_in_adm" method="POST" action="{{ route('admin.login.submit') }}">
           {{ csrf_field() }}
         <h1>Admin Login</h1>
         <div >
           <input type=email name=email placeholder="Email Address" value="{{ old('email') }}" required autofocus>
         </div>
         @if ($errors->has('email'))
         <span ><strong>{{ $errors->first('email') }}</strong></span>
         @endif
         <br>
         <div >
           <input type=password name=password placeholder="Password" required>
         </div>
         <br>
         <div >
           <button type=submit >SIGN IN</button>
         </div>
         </form>
        </div>
      </div>
     </div>
     <div ></div>
   </div>
  </div>
</body>
</html>

resources/views/ 目錄下新建立 dashboard.blade.php

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset=UTF-8>
    <meta name=viewport content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
        integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin=anonymous>
    <title>Admin Dashboard</title>
</head>

<body>
    <div>
        <div>
            <div></div>
            <div>
                <div>
                    <div>
                        <h1>Welcome To Admin Dashboard</h1>
                    </div>
                </div>
                <br><br>
                登入帳號: {{ $adminuser->email }}
                <br><br>
                <a href="/admin/logout">Logout</a>
            </div>
            <div></div>
        </div>
    </div>
</body>

</html>

在 app/Http/Controllers/Auth 目錄中新增一個 controller 給 admin 用,這個負責用來控制登入與登出。

php artisan make:controller Auth\AdminLoginController
<?php

namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Auth;
use Route;

class AdminLoginController extends Controller
{
    //先經過 middleware
    public function __construct()
    {
      $this->middleware('guest:admin', ['except' => ['logout']]);
    }
    //顯示 admin.login 視圖
    public function showLoginForm()
    {
      return view('admin.login');
    }
    //登入
    public function login(Request $request)
    {
      // 驗證表單資料
      $this->validate($request, [
        'email'   => 'required|email',
        'password' => 'required|min:6'
      ]);

      // 將表單資料送去驗證
      if (Auth::guard('admin')->attempt(['email' => $request->email, 'password' => $request->password], $request->remember)) {
        //驗證無誤轉入 admin.dashboard
        return redirect()->intended(route('admin.dashboard'));
      }
      // 驗證失敗 返回並拋出表單內容 只拋出 email 與 remember 欄位資料
      return redirect()->back()->withInput($request->only('email', 'remember'));
    }
    //登出
    public function logout()
    {
        Auth::guard('admin')->logout();
        return redirect('/admin');
    }
}

另外新增一個 controller 給 admin 用,這個負則用來控制 Admin 登入後的相關 function。(例如: 顯示 dashboard 或其他功能)

php artisan make:controller AdminController
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;

use Illuminate\Support\Facades\Auth;
use View;

class AdminController extends Controller

{
    /**
     * Create a new controller instance.
     * 進到這個控制器需要透過middleware檢驗是否為後台的使用者
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth:admin');
    }
    /**
     * 顯示 dashboard.
     * 並將 使用者的資料拋出
     * @return \Illuminate\Http\Response
     */
    public function dashboard()
    {
        $adminuser = Auth::user();
        return View::make('admin.dashboard', compact('adminuser'));
    }
}

編輯 routes/web.php 路由檔案,新增 admin 用的路由。

//admin用的路由 網址看起來就像 https://localhost/{admin}/{名稱}
Route::prefix('admin')->group(function() {
    Route::get('/login','Auth\AdminLoginController@showLoginForm')->name('admin.login');
    Route::post('/login', 'Auth\AdminLoginController@login')->name('admin.login.submit');
    Route::get('/logout', 'Auth\AdminLoginController@logout')->name('admin.logout');
    Route::get('/', 'Auth\AdminLoginController@showLoginForm')->name('admin');
    Route::get('/dashboard', 'AdminController@dashboard')->name('admin.dashboard');
}) ;

編輯 app/Exceptions/Handler.php 檔案,新增一個切換判斷是從哪個地方來的使用者並給出正確的位置視圖。

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

//新增以下使用兩個class
use Illuminate\Auth\AuthenticationException;
use Illuminate\Support\Arr;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Exception  $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Exception
     */
    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }
    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['error' => 'Unauthenticated.'], 401);
        }

        $guard = Arr::get($exception->guards(), 0);

        //用來判斷是前台還是後台來的使用者並轉到正確的登入頁面
        switch ($guard) {
            case 'admin':
            $login='admin.login';
            break;

            default:
            $login='login';
            break;
        }

        return redirect()->guest(route($login));
    }
}

編輯 app/Http/Middleware/RedirectifAuthenticated.php 檔案,當使用者被確認後,透過 middleware 來將使用者導到正確的視圖或功能位置。

<?php

namespace App\Http\Middleware;

use App\Providers\RouteServiceProvider;
use Closure;
use Illuminate\Support\Facades\Auth;

class RedirectIfAuthenticated
{
    /**
     * Handle an incoming request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Closure  $next
     * @param  string|null  $guard
     * @return mixed
     */
    public function handle($request, Closure $next, $guard = null)
    {
        // 舊有的判斷導到 Auth 的 RouteServiceProvider::HOME
        // if (Auth::guard($guard)->check()) {
        //     return redirect(RouteServiceProvider::HOME);
        // }
        // return $next($request);

        //當使用者被確認後,判斷是前台還是後台來的使用者並轉到正確的頁面位置
        switch ($guard) {
            case 'admin':
                if (Auth::guard($guard)->check()) {
                    return redirect()->route('admin.dashboard');
                }
            default:
                if (Auth::guard($guard)->check()) {
                    return redirect('/');
                }
                break;
        }
        return $next($request);
    }
}

完成。登入測試!

瀏覽列網址 localhost/admin 輸入帳號密碼按 SIGN IN 按紐
瀏覽列網址轉到 localhost/admin/dashboard 登入成功,並顯示登入帳號資料,按下 Logout 後會再轉回 localhost/admin 頁面。
最後修改日期: 2020 年 9 月 16 日