Try   HackMD

Laravel內建註冊&登入機制

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

利用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工具

安裝npm工具

Step 1.下載NVM安裝檔,它可以幫我們安裝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錯誤

原因是因為檔案的網址路徑出現錯誤,只需要告訴它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') }}">