實作Laravel 註冊、登入搭配JWT

更新於 2024/09/29閱讀時間約 29 分鐘

本篇純粹紀錄實作流程,以方便未來可以照此版繼續優化改進作法,這篇會使用Laravel 9版本並搭配Boostrap 5來做開發。

發現將每一次的實作作筆記,回頭再看的時候,就可以發現實作差異並進行改正,沒搞懂的底層操作也能在覆盤的時候理解,建議大家都要筆記自己的實作流程。

會員註冊設計

我們將用vite編譯工具來幫我們產生JS and CSS,詳細配置可以看一下先前的文章。 實作 Laravel 9 改用 vite 作為前端編譯檔案配置

首先先設計註冊畫面,創建一個命名為signUp.blade.php,附上範例code

@extends('layouts.app') 
@section('content')
<div class="row d-flex justify-content-center align-items-center h-100 vh-100">
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-2-strong" style="border-radius: 1rem;">
<div class="card-body p-5">
<form method="POST" action="{{ route('register') }}">
@csrf
<h3 class="mb-5 text-center">會員註冊</h3>

<div class="form-outline mb-4">
<label for="account" class="form-label">會員帳號</label>
<input
id="account"
type="text"
class="form-control form-control-lg"
placeholder="Account"
aria-label="Account"
aria-describedby="basic-addon1"
name="account"
/>
</div>

<div class="form-outline mb-4">
<label for="userName" class="form-label">會員名稱</label>
<input
id="userName"
type="text"
class="form-control form-control-lg"
placeholder="UserName"
aria-label="userName"
aria-describedby="basic-addon1"
name="userName"
/>
</div>

<div class="form-outline mb-4">
<label for="password" class="form-label">會員密碼</label>
<input
id="password"
type="password"
id="password"
class="form-control form-control-lg"
placeholder="Password"
aria-label="Password"
aria-describedby="basic-addon1"
name="password"
/>
</div>

<div class="form-outline mb-4">
<label for="password-confirm" class="form-label">確認密碼</label>
<input
id="password-confirm"
type="password"
class="form-control form-control-lg"
name="password_confirmation"
required
autocomplete="new-password"
placeholder="PasswordConfirm"
/>
</div>

<!-- button -->
<div class="d-grid gap-2">
<button class="btn btn-primary btn-lg" type="submit">
REGISTER
</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection

畫面長這樣(很簡陋的東西XDDDD)

raw-image

接著撰寫Controller邏輯

php artisan make:controller AuthController​

編寫取得signUp.blade.php View跟註冊 register邏輯方法

註:這邊function命名方式採用camelCase,駝峰命名方式,又稱小駝峰命名方式(lowerCamelCase)

<?php

namespace App\Http\Controllers;

use Exception;
use App\Models\User;
use Illuminate\Support\Str;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Hash;
use App\Http\Requests\RegisterRequest;

class AuthController extends Controller
{
public function signUp()
{
return view('signUp');
}

public function register(RegisterRequest $request)
{
$uid = Str::uuid();
$account = $request->request->get('account');
$userName = $request->request->get('userName');
$password = $request->request->get('password');

User::create([
'uid' => $uid,
'account' => $account,
'userName' => $userName,
'password' => bcrypt($password),
]);

return redirect()->route('signIn');
}
}

這邊的Request改採用Form Request來編寫,方便以後寫特定的Rules。

php artisan make:request RegisterRequest
raw-image

再來修改原本的migration table User Table的部分,修改部分為綠色code的樣子,主要是我的id想要用成uid的方式,email改為允許為null,主鍵改成uid,配置完成執行migrate

php artisan migrate
raw-image

接著配置User Model

<?php

namespace App\Models;

// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;

class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;

protected $primaryKey = 'uid';
protected $keyType = 'string';

protected $guarded = [];

/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'uid',
'userName',
'account',
'email',
'password',
];

/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];

/**
* The attributes that should be cast.
*
* @var array<string, string>
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
}

配置路由web.php檔案,而路由檔支持的寫法有很多種,詳下圖

raw-image

接下來確認新增都沒問題就大功完成註冊的部分~

raw-image

會員登入設計

會員登入的畫面拿註冊畫面來改,一樣先創建signIn.blade.php畫面

@extends('layouts.app')

@section('content')
<div class="row d-flex justify-content-center align-items-center h-100 vh-100">
<div class="col-12 col-md-8 col-lg-6 col-xl-5">
<div class="card shadow-2-strong" style="border-radius: 1rem;">
<div class="card-body p-5">
<form action="{{ route('login') }}" method="post" enctype="multipart/form-data">
@csrf
<h3 class="mb-5 text-center">LOGIN</h3>

<div class="form-outline mb-4">
<label for="account" class="form-label">會員帳號</label>
<input id="account" type="text" class="form-control form-control-lg" placeholder="Account"
aria-label="Account" aria-describedby="basic-addon1" name="account">
</div>

<div class="form-outline mb-4">
<label for="password" class="form-label">會員密碼</label>
<input id="password" type="password" id="password" class="form-control form-control-lg"
placeholder="Password" aria-label="Password" aria-describedby="basic-addon1" name="password">
</div>

<!-- Checkbox -->
{{-- <div class="form-check d-flex justify-content-start mb-4">
<input class="form-check-input" type="checkbox" value="" id="form1Example3" />
<label class="form-check-label" for="form1Example3"> Remember password </label>
</div> --}}


<!-- button -->
<div class="d-grid gap-2">
<a type="submit" id="create_form" class="btn btn-primary btn-lg">Login</a>
{{-- <button class="btn btn-primary btn-lg" type="submit" id="create_form">Login</button> --}}
<hr class="my-2">
<button class="btn btn-lg btn-block btn-primary" style="background-color: #dd4b39;"
type="submit"><i class="fab fa-google me-2"></i> Sign in with google</button>
<hr class="my-2">
<button class="btn btn-lg btn-block btn-primary mb-2" style="background-color: #3b5998;"
type="submit"><i class="fab fa-facebook-f me-2"></i>Sign in with facebook</button>
</div>
</form>
</div>
</div>
</div>
</div>
@endsection




安裝JWT並產生Token

這邊使用tymon/jwt-auth 套件,並根據使用文檔配置,來設定我們的Private Key,並搭配 firebase/php-jwt,來創建我們的Token

composer require tymon/jwt-auth

配置vendor,接著會產生config/jwt.php檔案,有些設定可以在這邊改

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

產生金鑰

php artisan jwt:secret

安裝firebase/php-jwt

composer require firebase/php-jwt

接著開始寫產生Token的程式邏輯,這邊創建Services/AuthService.php 檔案,並定義一個encode方法

raw-image

接著修改AuthController檔案,增加login方法,驗證登入帳密及產生Token,並由Service端把token塞到cookie,方便前端取用。

Token在前端保存有多種方式,額外再寫一篇補充說明,看完一些文件說明,大致上沒有一定需要怎麼做🧐

<?php

namespace App\Http\Controllers;

use Exception;
use App\Models\User;
use Illuminate\Support\Str;
use App\Services\AuthService;
use App\Http\Requests\LoginRequest;
use Illuminate\Support\Facades\Hash;
use App\Http\Requests\RegisterRequest;

class AuthController extends Controller
{
private AuthService $authService;

public function __construct(
AuthService $authService
) {
$this->authService = $authService;
}

public function signUp()
{
return view('signUp');
}

public function signIn()
{
return view('signIn');
}

public function register(RegisterRequest $request)
{
$uid = Str::uuid();
$account = $request->request->get('account');
$userName = $request->request->get('userName');
$password = $request->request->get('password');

User::create([
'uid' => $uid,
'account' => $account,
'userName' => $userName,
'password' => bcrypt($password),
]);

return redirect()->route('signIn');
}

public function login(LoginRequest $request)
{
$account = $request->request->get('account');
$password = $request->request->get('password');

$userData = User::where('account', $account)->first();

if (!$userData || !Hash::check($password, $userData->password)) {
throw new Exception('密碼錯誤');
}

$token = $this->authService->encode($userData);

$minutes = 5;
return response()->json([
'status' => 'success',
'data' => [
'access_token' => $token,
'token_type' => 'bearer',
'expired_at' => now()->addMinutes(config('jwt.ttl'))->timestamp
]
])->withCookie(cookie('token', $token, $minutes));
}

}

新增login.js檔案,並使用AJAX處理,在登入成功確認response的結果是否有Token。

raw-image

接著測試登入結果有正常取得Token結果

raw-image
raw-image


















avatar-img
15會員
37內容數
學涯無止境,透過每日or每週模仿學習筆記,不管是哪些領域也好,總有一天也可以從菜雞變小雞
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
你可能也想看
Google News 追蹤
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
延續上篇: 功能實作篇 框架與結構 接下來我們將深入實作 Laravel 框架中的路由(Router)、控制器(Controller)、業務邏輯(Service)、儲存庫模式(Repository Pattern),以及模型(Model)的細節。這些部分將構成我們縮網址系統的核心功能。
Thumbnail
本篇將涵蓋環境設置和基礎結構的搭建,包括 Laravel 框架的初始化、路由設置、資料庫遷移和模型的建立。下篇將進一步討論核心功能的實現,包括 API 的開發和核心邏輯的實作。
Thumbnail
在 IG 上看到一位前端大大用 Google Apps Script + Line bot 替自己的球隊安排了球經,覺得很有趣,想來玩看看
Thumbnail
最近剛好分配一個需求,要批次更新一些基礎設定資料,而新系統基礎設定資料都統一由別的團隊維護在Google Sheet 上,一開始是要我寫 Laravel Seeder 塞資料表,後來發現也太多數據要批次更新了,數據要對到何時何年,乾脆來研究串 Google Sheet API 整批塞入在對總行數就好
Thumbnail
在撰寫專案時,有時候可能需要做一些特定Exceptions 來拋出error message的情況,而在不同公司任職,大家配置的流程可能就有些不同,這邊將簡單練習如何配置自定義的Exception。
Thumbnail
「斜槓」一詞,在近幾年相當流行,人人都發現 : 只會一項專業是不夠的。但「早上在早餐店打工、下午跑外送、晚上擔任兼職教練」,這樣的生活方式,算是斜槓嗎? 斜槓的目的是什麼? 該如何選擇,才能讓每件事有加乘效果? 過往是運動員的他,是如何跨領域並創業? 在每個關鍵點與身分轉換,他又是如何抓住機會?
Thumbnail
初學者有時候無法順利執行RPA流程,可能只是因為未能留意系統的預設情況,因此我們在日期與時間(基礎篇)中,先簡單說明基本的時間格式與設定方法,協助初學者進行除錯,而進階篇則將透過實際操作,讓已經熟悉UiPath的學習者能靈活應用、加深印象!
Thumbnail
在上一篇Notion實作文章中,我們已經將大部分的功能解釋完了。在這篇文章中,我們將會專注在建立管理讀書進度的資料庫。 我先來說明一下我想要這個資料庫達成的事情: 我可以根據我對知識的掌握程度訂定隔幾天之後要再複習,並利用上次複習時間讓這個資料庫自動計算、過濾出每天我該複習什麼。
Thumbnail
本文使用網站的 FB 登入做示範 採用 Laravel 8 + Socialite 5 使用 Session 記錄狀態 不同版本可能會有些許語法及方法上的差異,請自行調整 前言 最近因為碰到需要實作 OAuth 第三方登入的需求,只好把之前隨便看看的東西撿回來研究並實作。不過我找到多數現存的中文文章
Thumbnail
*合作聲明與警語: 本文係由國泰世華銀行邀稿。 證券服務係由國泰世華銀行辦理共同行銷證券經紀開戶業務,定期定額(股)服務由國泰綜合證券提供。   剛出社會的時候,很常在各種 Podcast 或 YouTube 甚至是在朋友間聊天,都會聽到各種市場動態、理財話題,像是:聯準會降息或是近期哪些科
Thumbnail
延續上篇: 功能實作篇 框架與結構 接下來我們將深入實作 Laravel 框架中的路由(Router)、控制器(Controller)、業務邏輯(Service)、儲存庫模式(Repository Pattern),以及模型(Model)的細節。這些部分將構成我們縮網址系統的核心功能。
Thumbnail
本篇將涵蓋環境設置和基礎結構的搭建,包括 Laravel 框架的初始化、路由設置、資料庫遷移和模型的建立。下篇將進一步討論核心功能的實現,包括 API 的開發和核心邏輯的實作。
Thumbnail
在 IG 上看到一位前端大大用 Google Apps Script + Line bot 替自己的球隊安排了球經,覺得很有趣,想來玩看看
Thumbnail
最近剛好分配一個需求,要批次更新一些基礎設定資料,而新系統基礎設定資料都統一由別的團隊維護在Google Sheet 上,一開始是要我寫 Laravel Seeder 塞資料表,後來發現也太多數據要批次更新了,數據要對到何時何年,乾脆來研究串 Google Sheet API 整批塞入在對總行數就好
Thumbnail
在撰寫專案時,有時候可能需要做一些特定Exceptions 來拋出error message的情況,而在不同公司任職,大家配置的流程可能就有些不同,這邊將簡單練習如何配置自定義的Exception。
Thumbnail
「斜槓」一詞,在近幾年相當流行,人人都發現 : 只會一項專業是不夠的。但「早上在早餐店打工、下午跑外送、晚上擔任兼職教練」,這樣的生活方式,算是斜槓嗎? 斜槓的目的是什麼? 該如何選擇,才能讓每件事有加乘效果? 過往是運動員的他,是如何跨領域並創業? 在每個關鍵點與身分轉換,他又是如何抓住機會?
Thumbnail
初學者有時候無法順利執行RPA流程,可能只是因為未能留意系統的預設情況,因此我們在日期與時間(基礎篇)中,先簡單說明基本的時間格式與設定方法,協助初學者進行除錯,而進階篇則將透過實際操作,讓已經熟悉UiPath的學習者能靈活應用、加深印象!
Thumbnail
在上一篇Notion實作文章中,我們已經將大部分的功能解釋完了。在這篇文章中,我們將會專注在建立管理讀書進度的資料庫。 我先來說明一下我想要這個資料庫達成的事情: 我可以根據我對知識的掌握程度訂定隔幾天之後要再複習,並利用上次複習時間讓這個資料庫自動計算、過濾出每天我該複習什麼。
Thumbnail
本文使用網站的 FB 登入做示範 採用 Laravel 8 + Socialite 5 使用 Session 記錄狀態 不同版本可能會有些許語法及方法上的差異,請自行調整 前言 最近因為碰到需要實作 OAuth 第三方登入的需求,只好把之前隨便看看的東西撿回來研究並實作。不過我找到多數現存的中文文章