---
# System prepended metadata

title: Laravel內建註冊&登入機制
tags: [laravel]

---

---
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') }}">
```