做網站總免不了要處理使用者登入、註冊、認証授權…的工作, Laravel 這個 PHP 框架很好心的內建了一整套給你,只要呼叫 php artisan make:auth
再給它適當的資料庫權限執行他的 mirgration sql ,幾乎就可以無痛地擁有一套使用者管理系統,以下是一點使用及客製化的筆記
在資料庫建立使用者的資料表,如果使用
database/migrations
下 create user table 的程式讓 Laravel 幫你建的話,名稱預設會叫 Users (這跟 Laravel 使用 Eloquent Model 的方式有關),不想叫這個名字也沒關係,之後可以改掉。至於資料表中的欄位,Laravel 的要求只有兩個,一個是 password 的欄位長度至少要 60 個字視,而若是要啟用 remember me 功能,要有個至少100 字元長度的 remember_token 的欄位。在專案的
app/Models
下建立 Eloquent Model Users ( Models 目錄要自行建立),Laravel 預設會使用default
的 db connection 連到 Users 這個資料表,並以 id 當 primary key 查詢,若是這三個條件都不想用預設值,那也只要指定好 Users 中 $table / $primaryKey / $connection 三個屬性即可。1234567891011121314151617181920212223242526272829<?phpnamespace App;use Illuminate\Notifications\Notifiable;use Illuminate\Foundation\Auth\User as Authenticatable;class User extends Authenticatable{use Notifiable;protected $table = 'User';/** primary key of the table **/public $primaryKey = 'my_primary_key';/** database connection name in database.php **/protected $connection = 'my_connection';/*** The attributes that are mass assignable.** @var array*/protected $fillable = ['name', 'email', 'password', 'username'];/*** The attributes that should be hidden for arrays.** @var array*/protected $hidden = ['password', 'remember_token',];}編輯
config/auth.php
修改認証設定,剛開始沒有太搞怪的話,應該只要修改 User Providers 區塊,把 users 這個 model 指到對的 class 去就好12345678...skip'providers' => ['users' => ['driver' => 'eloquent','model' => App\Models\Users::class,],],...skip設定相關路由。如果一開頭使用
php artisan make:auth
的話,它會在路由設定檔中routes/web.app
( 5.4 之前的版本好像是在專案根目錄下的routes.php
) 加上一行Auth::routes()
,執行的php artisan route:list
會發現多出一大串的路由設定如下,除了 home 用auth
外,其他的自動套用guest
這個 middleware12345678910| GET|HEAD | home | | App\Http\Controllers\HomeController@index | web,auth || POST | login | | App\Http\Controllers\Auth\LoginController@login | web,guest || GET|HEAD | login | login | App\Http\Controllers\Auth\LoginController@showLoginForm | web,guest || POST | logout | logout | App\Http\Controllers\Auth\LoginController@logout | web || POST | password/email | password.email | App\Http\Controllers\Auth\ForgotPasswordController@sendResetLinkEmail | web,guest || GET|HEAD | password/reset | password.request | App\Http\Controllers\Auth\ForgotPasswordController@showLinkRequestForm | web,guest || POST | password/reset | | App\Http\Controllers\Auth\ResetPasswordController@reset | web,guest || GET|HEAD | password/reset/{token} | password.reset | App\Http\Controllers\Auth\ResetPasswordController@showResetForm | web,guest || GET|HEAD | register | register | App\Http\Controllers\Auth\RegisterController@showRegistrationForm | web,guest || POST | register | | App\Http\Controllers\Auth\RegisterController@register | web,guest |上面這一串完整的 code 在
https://github.com/laravel/framework/blob/5.4/src/Illuminate/Routing/Router.php
中123456789101112131415public function auth(){// Authentication Routes...$this->get('login', 'Auth\LoginController@showLoginForm')->name('login');$this->post('login', 'Auth\LoginController@login');$this->post('logout', 'Auth\LoginController@logout')->name('logout');// Registration Routes...$this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');$this->post('register', 'Auth\RegisterController@register');// Password Reset Routes...$this->get('password/reset', 'Auth\ForgotPasswordController@showLinkRequestForm')->name('password.request');$this->post('password/email', 'Auth\ForgotPasswordController@sendResetLinkEmail')->name('password.email');$this->get('password/reset/{token}', 'Auth\ResetPasswordController@showResetForm')->name('password.reset');$this->post('password/reset', 'Auth\ResetPasswordController@reset');}由於這個專案僅需要使用者登入認証的部份,所以手動在
routes/web.php
中加入包含登入認証、登入的網頁、登出、及登入後顯示的頁面共四個路由,避免不必要的路由變成沒人管理、被入侵的點123456...skipRoute::post('/login', 'App\Http\Controllers\Auth\myController@login');Route::get('/login', 'App\Http\Controllers\Auth\myController@showLoginForm')->name('login');Route::post('/logout', 'App\Http\Controllers\Auth\myController@logout')->name('logout');Route::get('/home', 'HomeController@index');...skip有了路由後,接著要來寫處理路由的 Controller 了 (app/Http/Controllers/myController.php)。Laravel 生的代碼如下,其中 $redirectTo 指定在完成登入後要導到那去. 另外,預設是使用 email 欄位當帳號,如果要用其他欄位當帳話的話,要自行加一個 username () 函式回傳要當帳號的植位名稱,這邊是用 username 當範例。至於在路由中寫的 login / showLoginForm / logout 三個函式並沒有明確地寫在這邊。相關的函式 Laravel 寫在 AuthenticateUsers 這個 trait 中,透過 use 注入到 class 中,如果有客製的需求,自行覆寫掉即可 ( username() 即是被覆寫掉的函式)。另外,Laravel 的範例中,會在建構子中加入路由的 middleware ,先前看到的
guest
就是在這個時候加進來的12345678910111213141516<?phpnamespace App\Http\Controllers;use App\Http\Controllers\Controller;use Illuminate\Foundation\Auth\AuthenticatesUsers;class myController extends Controller{use AuthenticatesUsers;protected $redirectTo = '/home';public function __construct(){$this->middleware('guest', ['except' => 'logout']);}public function username(){return 'username';}}編寫登入表單的網頁,由於我們等下要使用內建的登入路由,它會去叫用
resources/views/auth/login.blade.php
,所以只能乖乖的生一個給它,如果不想用這個預設的路徑,可以在login controller 中覆寫showLoginForm()
直接回使你要使用的 view 即可。123456789101112131415161718192021222324252627282930313233343536373839404142<form class="form-horizontal" role="form" method="POST" action="{{ route('login') }}">{{ csrf_field() }}<div class="form-group{{ $errors->has('account') ? ' has-error' : '' }}"><label for="account" class="col-md-4 control-label">Account</label><div class="col-md-6"><input id="account" type="text" class="form-control" name="account" value="{{ old('account') }}" autofocus>@if ($errors->has('account'))<span class="help-block"><strong>{{ $errors->first('account') }}</strong></span>@endif</div></div><div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}"><label for="password" class="col-md-4 control-label">Password</label><div class="col-md-6"><input id="password" type="password" class="form-control" name="password" required>@if ($errors->has('password'))<span class="help-block"><strong>{{ $errors->first('password') }}</strong></span>@endif</div></div><div class="form-group"><div class="col-md-6 col-md-offset-4"><div class="checkbox"><label><input type="checkbox" name="remember" {{ old('remember') ? 'checked' : '' }}> Remember Me</label></div></div></div><div class="form-group"><div class="col-md-8 col-md-offset-4"><button type="submit" class="btn btn-primary">Login</button></div></div></form>補一個登入後顯示頁面的 controller
app/Http/Controller/HomeController.php
及網頁resources/views/home.blade.php
12345678910<?phpnamespace App\Http\Controllers;use Illuminate\Http\Request;class HomeController extends Controller{public function index(){return view('home');}}
|
|
這幾個登入認証相關的路由都會經過的
guest
middleware 是定義在app/Kernel.php
中,指到app/Http/Middleware/RedirectIfAuthenticated.php
,Laravel 預設的程式碼很簡單,大概就是要是已經登入了的話,那就跳到 /home 去,要是沒有,就跳到原先指定的網址,這邊的程式碼是寫死的,要是登入後的首頁不叫 /home ,要記得改一下。12345678public function handle($request, Closure $next, $guard = null){if (Auth::guard($guard)->check()) {return redirect('/home');}return $next($request);}如果以上寫的沒什麼問題,打開網頁 /login , 因為沒登入過,所以
guest
中的登入判定會失敗,會轉到指定的 /login 看到登入的表單。送出登入後,會 post 給 myController 的 login 函式處理,若是成功就跳到 $redirectTo 指定的網址(/home),要是失敗就送回失敗訊息。之後若是再打開 /login , 因為登入判定成功,會直接轉到 /home 去,而後其他頁面若是要判定是否登入,只要用Auth::check()
即可。由於登入檢查幾乎是制式的語法,可以仿照guest
寫一個 auth 的 middleware 套在需要檢查的路由前自動執行。收工。p.s 若是要取用登入者的資訊,可以使用
$user = Auth::user()
的方式,或是透過 eloquent 威能,用Auth::id()
取得屬性值。