使用Laravel Sanctum實作註冊登入登出

Laravel 7新增了Sanctum讓登入驗證流程更加方便,Sanctum不像passport要用到Oath2,而簡化了許多功能。比起passport,小應用或SPA更加適合使用Sanctum

準備

安裝sanctum

1
composer require laravel/sanctum

發佈設定檔

1
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"

建立資料庫

1
php artisan migrate

Middleware設定

我們要給Api設定Middleware才能跑登入流程,拿取使用者資料

1
2
3
4
5
6
7
8
//app/Http/Kernel.php
use Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful;

'api' => [
EnsureFrontendRequestsAreStateful::class,
'throttle:60,1',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],

註冊

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
public function signUp(Request $request){
//驗證資料
$request->validate([
'name' => 'required',
'email' => 'required|email',
'password' => 'required',
]);

//查詢是否存在
$user = User::where('email', $request->email)->first();
if ($user != null) {
$data = [
"method" => "sign up",
"message" => "already sign",
];
return response()->json($data, 401);
}

//建立帳戶
$user = User::create([
'sign_up_date' => date('Y-m-d'),
'name' => $request['name'],
'email' => $request['email'],
'password' => bcrypt($request['password']),
]);

if ($user != null) {
$data = [
"method" => "sign up",
"message" => "success",
];
return response()->json($data, 200);
} else {
$data = [
"method" => "sign up",
"message" => "unexpected error",
];
return response()->json($data, 500);
}
}

登入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public function getToken(Request $request){
//驗證資料
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required'
]);

$user = User::where('email', $request->email)->first();

if (!$user || !Hash::check($request->password, $user->password)) {
$data = [
"method" => "login",
"message" => "failed",
"data" => [
"access_token" => "",
"user_name" => "",
]
];
return response()->json($data, 401);
} else {
$data = [
"method" => "login",
"status_code" => "200",
"message" => "success",
"data" => [
"access_token" => $user->createToken($request->device_name)->plainTextToken,
"user_name" => $user->name,
]
];
return response()->json($data, 200);
}
}

登出

1
2
3
public function deleteToken(Request $request){
$request->user()->tokens()->where('name', $request->device_name)->delete();
}

如果使用Vue的話,可使用Vuex儲存token和不機密的使用者資料,也可為token設定範圍,區分管理者和用戶的權限。