--- tags: laravel --- # Laravel內建註冊&登入機制 ![](https://i.imgur.com/zF80okP.png) 利用Laravel自帶的驗證機制,來實現帳密登入.忘記密碼等功能 登入路徑 /login 註冊路徑 /register ## 快速啟用註冊登入機制 **Laravel 5** Step 1.開啟Terminal,輸入 php artisan make:auth Step 2.Laravel會自動生出所需要的視圖與路由規則 **Laravel 6~7** ==前台改用vue,所以方法有變== Step 1.下載laravel/ui套件後生成所需視圖與規則,開啟Terminal,輸入以下指令: composer require laravel/ui php artisan ui vue --auth Step 2.編譯js檔案,開啟Terminal,輸入以下指令 npm install npm run dev **Laravel 8.x** ==改用官方套件jetstream,方法又變了== Step 1.下載laravel/jetstream套件,生成所需要的資源檔與Migration composer require laravel/jetstream php artisan jetstream:install livewire Step 2.編譯js檔案,開啟Terminal,輸入以下指令 npm install npm run dev PS:[需先安裝npm工具](https://medium.com/html-test/%E5%BE%9E%E9%9B%B6%E9%96%8B%E5%A7%8B-%E4%BD%BF%E7%94%A8npm%E5%A5%97%E4%BB%B6-317beefdf182) ### 安裝npm工具 Step 1.下載[NVM安裝檔](https://nodejs.org/en/),它可以幫我們安裝npm和node Step 2.開啟Terminal,執行npm -v 以確認是否安裝成功 ## 在生成專案時,直接加入jetstream框架 如果您正在生成一個全新的應用程式,並且希望包含身份驗證框架,則可以在創建應用程式時使用 --jet 指令。 此命令將創建一個新的應用程式,並編譯安裝所有身份驗證框架: `laravel new 專案名稱 --jet` ## 自定義Quick Start 5~7 版本 ### 變更登入頁面 ``` //app/Http/Controllers/Auth/LoginController.php //改用auth/login2.blade.php作為登入頁面 public function showLoginForm() { return view('auth.login2'); } ``` ### 變更註冊頁面 //app/Http/Controllers/Auth/RegisterController.php //改用auth/register2.blade.php作為註冊頁面 public function showRegistrationForm() { return view('auth.register2'); } ### 變更登入後轉址路徑 ``` //app/Http/Controllers/Auth/LoginController.php protected $redirectTo = '/home'; //登入後轉址到/home //函式版本的優先級較高,可根據邏輯決定導到哪個網址 public function redirectTo(){ if(Auth::user()->role_id == 2){ //假如是一般使用者 return '/home'; }else if(Auth::user()->role_id == 1){ //假如是管理員 return '/admin'; }else{ return '/login'; } } ``` ### 設定登出網址 ``` //app/Http/Controllers/Auth/LoginController.php use Illuminate\Http\Request; //設定登出網址 protected function loggedOut(Request $request) { return redirect('/my/logout/path'); } ``` ### 變更登入時的驗證欄位,改用帳號登入 Step 0.users表格內建沒有username欄位,先修改migration後更新表格,然後加入資料 Step 1.在 app/Http/Controllers/Auth/LoginController.php 加入username() ``` //app/Http/Controllers/Auth/LoginController.php public function username(){ return 'username'; } ``` ==提醒:請注意App\User.php的$fillable白名單屬性有加上username,否則會無法寫入此欄位== Step 2.修改登入視圖 將email部分的內容改成帳號 ``` //resources/views/auth/login.blade.php <div class="form-group row"> <label for="username" class="col-md-4 col-form-label text-md-right">帳號</label> <div class="col-md-6"> <input id="username" type="username" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autocomplete="username" autofocus> @error('username') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> ``` ### 在註冊頁面新增欄位,比如帳號 Step 1.修改註冊頁面,加入帳號欄位的輸入項 ``` <div class="form-group row"> <label for="username" class="col-md-4 col-form-label text-md-right">帳號</label> <div class="col-md-6"> <input id="username" type="text" class="form-control @error('username') is-invalid @enderror" name="username" value="{{ old('username') }}" required autocomplete="username" autofocus> @error('username') <span class="invalid-feedback" role="alert"> <strong>{{ $message }}</strong> </span> @enderror </div> </div> ``` Step 2.修改users表格的migration檔案,加入所需要的欄位 Step 3.修改Model類別 User的$fillable屬性,加入新欄位 Step 4.修改RegisterController.php控制器的validator()和create() ``` \\app\Http\Controllers\RegisterController.php //這個方法負責註冊表單的驗證 protected function validator(array $data) { return Validator::make($data, [ 'username' => ['required', 'string', 'max:255'], 'name' => ['required', 'string', 'max:255'], 'email' => ['required', 'string', 'email', 'max:255', 'unique:users'], 'password' => ['required', 'string', 'min:8', 'confirmed'], ]); } //這個方法負責將註冊表單的資料寫入資料庫 protected function create(array $data) { return User::create([ 'username' => $data['username'], 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), ]); } ``` ### 變更重設密碼的 Email 內容(補充技巧) Step 1.生成Notification檔案,指令如下 `php artisan make:notification PasswordReset` Step 2.編輯PasswordReset.php ``` //app/Notifications/PasswordReset.php public $token; public function __construct($token) { $this->token = $token; } public function toMail($notifiable) { return (new MailMessage) ->subject('Email主旨') ->line('重設密碼訊息第一行') ->action('重設密碼', url('password/reset',$this->token)) ->line('重設密碼第二行'); } ``` Step 3.修改 User Model,加入以下內容: ``` //app/User.php; public function sendPasswordResetNotificatoin($token){ $this->notify(new ReminderNotification($token)); } ``` PS:需載入Notifiable Class,否則會出現以下錯誤 Call to undefined method,作法如下: ... ``` use Illuminate\Notifications\Notifiable; use App\Notifications\PasswordReset; class User extends Authenticatable { use Notifiable; } ``` Step 4.複寫視圖 Layout,需複寫原始視圖到 resources資料夾,指令如下: `php artisan vendor:publish` 編輯視圖檔 /resources/views/vendor/notifications ## 自定義Quick Start 8.x 版本 如前所述,laravel/jetstream套件的 php artisan jetstream:install 命令將創建驗證所需的所有視圖,並將它們放在 resources/views/auth 的資料夾底下。 Jetstream 還將創建一個 resources/views/layouts 資料夾,其中包含應用程式的基本布局。這些驗證視圖都使用 Tailwind CSS 框架,但是你可以按你的意願自由地客製它們。 如果樣式表沒抓到導致跑版,請修改resources/views/layouts/guest.blade.php >也可修改mix-manifest.json,在路徑前面加個. ### 變更登入頁面 修改resources/views/login.blade.php ### 變更註冊頁面 Step 1.修改resources/views/register.blade.php Step 2.修改app/Fortify/CreateNewUser.php Step 3.修改app/Models/User.php ### 變更登入後轉址路徑 修改app/Providers/RouteServiceProvider.php,改動如下: `public const HOME = '/登入後轉址路徑'` ### 設定登出網址 Step 1.在app\Responses資料夾內加入以下檔案 > Responses資料夾可能不存在,需要自己新增 ``` <?php namespace App\Responses; use Illuminate\Http\JsonResponse; use Illuminate\Http\Response; use Laravel\Fortify\Contracts\LogoutResponse as LogoutResponseContract; class LogoutResponse implements LogoutResponseContract { /** * Create an HTTP response that represents the object. * * @param \Illuminate\Http\Request $request * @return \Symfony\Component\HttpFoundation\Response */ public function toResponse($request) { return $request->wantsJson() ? new JsonResponse('', 204) : redirect('/logout'); //登出時轉址路徑 } } ``` Step 2.在app/Providers/FortifyServiceProvider.php加入以下內容 ``` use App\Responses\LogoutResponse; use Laravel\Fortify\Contracts\LogoutResponse as LogoutResponseContract; ... public function register() { $this->app->bind( LogoutResponseContract::class, LogoutResponse::class ); } ``` ### 變更登入時的驗證欄位,改用帳號登入 Step 1.修改resources/views/login.blade.php,將email欄位改為username Step 2.修改config/fortify.php,將'username'的值改為username ### 在註冊頁面新增欄位,比如帳號 Step 1.修改resources/views/register.blade.php Step 2.修改app/Fortify/CreateNewUser.php Step 3.修改app/Models/User.php ### 修改需要登入時的行為 修改app/Http/Middleware/Authenticate.php的redirectTo() ## 驗證相關幫助方法 取得登入用戶 * Auth::user() 取得登入用戶實例 * Auth::id() 取得登入用戶主鍵 * $request->user() 取得登入用戶實例 範例碼 ``` public function who(Request $request) { //取得登入用戶 dd(Auth::user()->id); //取得登入用戶主鍵 dd(Auth::id()); //取得登入用戶 dd($request->user()); } ``` 用程式進行登入 * Auth::login($user) * Auth::login($user,true) //登入並記得我 * Auth::loginUsingId($id) //使用用戶id進行登入 * Auth::guard(‘admin’)->login($user) 範例碼 ``` public function selflogin() { $user = User::findOrFail(13); Auth::login($user); } ``` 用程式進行登出 * Auth::logout() 範例碼 ``` public function logout() { Auth::logout(); } ``` 確認是否完成登入 * Auth::check() 範例碼 ``` public function checkAuth() { dd(Auth::check()); } ``` ### 驗證控制器 透過Controller建構子來設定 ``` public function __construct(){ //這個控制器的所有方法都需要通過驗證 $this->middleware('auth'); } ``` ### 驗證路由 要加入內建的驗證路由,只需要在web.php加入以下規則即可。也可透過php artisan make:auth指令生成 `Auth::routes()` 如需要移除註冊功能的具體作法 Step 1.刪除RegisterController.php Step 2.修改驗證路由如下 Auth::routes(['register'=>'false']); #### 讓路由規則需要登入後才能訪問 方法1 在路由後面加上middleware('auth'); ``` \\routes\web.php //需要驗證才能訪問的路由 Route::get('/home', 'HomeController@index')->middleware('auth'); ``` 方法2 在路由群組加上 middleware for auth ``` \\routes\web.php Route::group(['middleware' => 'auth'], function() { //需要驗證才能訪問的路由 Route::get('/home', 'HomeController@index'); }); ``` #### 設定簡單驗證的路由 用於沒有登入頁面可用時,會跳出輸入使用者名稱和密碼的popup視窗,請在使用者名稱輸入email ``` \\routes\web.php Route::group(['middleware' => 'auth.basic'], function() { //需要驗證才能訪問的路由 Route::get('/home', 'HomeController@index'); }); ``` #### 設定未登入用戶訪問驗證路由的轉址 找到app\Http\Middleware\Authenicate.php後實作redirectTo() 範例碼 ``` protected function redirectTo($request) { if (! $request->expectsJson()) { //如果未登入則轉址到/403 return '/403'; } } ``` ## 將Voyager的登入頁面改成使用username進行登入 ### Step 1.複寫login.blade.php 從 vendor/tcg/voyager/resources/views/login.blade.php 複製到 resources/views/vendor/voyager/login.blade.php 將此login.blade.php的email輸入項改為username 範例碼 ``` <div class="form-group form-group-default" id="usernameGroup"> <label>帳號</label> <div class="controls"> <input type="text" name="username" id="username" value="{{ old('username') }}" placeholder="請輸入帳號" class="form-control" required> </div> </div> ``` Step 2.修改voyager.php的namespace設定,指向到自己的專案 ``` //config/voyager.php 'controllers' => [ //'namespace' => 'TCG\\Voyager\\Http\\Controllers', 'namespace' => 'App\\Http\\Controllers\\Voyager', ], ``` Step 3.將所有Voyager控制器複製一份到自己的專案,路徑在App\\Http\\Controllers\\Voyager 開啟Terminal,輸入以下指令 `php artisan voyager:controller` ==出現以下錯誤,表示Step2並沒有完成 The controllers namespace must start with your application namespace: App</error>== Step 4.在VoyagerAuthController.php加入username(),回傳username ``` \\App\\Http\\Controllers\Voyager\\VoyagerAuthController.php public function username(){ return 'username'; } ``` ## 問題排除 ### 當使用XAMPP開發環境時,出現如下圖的找不到livewire.js的404錯誤 ![](https://i.imgur.com/ab7kIch.png) 原因是因為檔案的網址路徑出現錯誤,只需要告訴它livewire檔案的正確網址即可 Step 1.開啟Terminal,輸入以下指令 `php artisan vendor:publish --tag=livewire:config` Step 2.修改config/livewire.php,將asset_url改成正確的網址路徑 `'asset_url' => 'http://localhost:6080/form/public',` ### 本地端因為網址的關係,導致二階段驗證的表單網址錯誤,功能無法正常執行 原因是使用XAMPP,網址路徑問題導致表單指向的路徑不正確導致,解法是修改成resources/views/auth/two-factor-challenge.blade.php的以下內容 ``` line 18 <form method="POST" action="{{ url('/two-factor-challenge') }}"> ```