在開發Api時,處理客戶端請求之前,需要對用戶進行身份認證,Laravel框架默認為我們提供了一套用戶認證體系,在進行web開發時,幾乎不用添加修改任何代碼,可直接使用,但在進行api開發時,需要我們自己去實現,並且Laravel框架默認提供的身份認證不是jwt的,需要在數據庫中增加api_token字段,記錄用戶認證token並進行身份校驗,如果需要使用jwt,無需添加字段,需要借助三方庫來實現。
Token認證原理
-
客戶端發送認證信息 (一般就是用戶名 / 密碼), 向服務器發送請求
-
服務器驗證客戶端的認證信息,驗證成功之后,服務器向客戶端返回一個 加密的 token (一般情況下就是一個字符串)
-
客戶端存儲 (cookie, session, app 中都可以存儲) 這個 token, 在之后每次向服務器發送請求時,都攜帶上這個 token
-
服務器驗證這個 token 的合法性,只要驗證通過,服務器就認為該請求是一個合法的請求
JWT概述
token 只是一種思路,一種解決用戶授權問題的思考方式,基於這種思路,針對不同的場景可以有很多種的實現。而在眾多的實現中,JWT (JSON Web Token) 的實現最為流行.
JWT 這個標准提供了一系列如何創建具體 token 的方法,這些緣故方法和規范可以讓我們創建 token 的過程變得更加合理和效率.
比如,傳統的做法中,服務器會保存生成的 token, 當客戶端發送來 token 時,與服務器的進行比對,但是 jwt 的不需要在服務器保存任何 token, 而是使用一套加密 / 解密算法 和 一個密鑰 來對用戶發來的 token 進行解密,解密成功后就可以得到這個用戶的信息.
這樣的做法同時也增加了多服務器時的擴展性,在傳統的 token 驗證中,一旦用戶發來 token, 那么必須要先找到存儲這個 token 的服務器是哪台服務器,然后由那一台服務器進行驗證用戶身份。而 jwt 的存在,只要每一台服務器都知道解密密鑰,那么每一台服務器都可以擁有驗證用戶身份的能力.
這樣一來,服務器就不再保存任何用戶授權的信息了,也就解決了 session 曾出現的問題.
實現方法
1.安裝 jwt-auth
composer require tymon/jwt-auth:dev-develop
參考文檔:
https://github.com/tymondesigns/jwt-auth/wiki/Installation
2.在 config/app.php
的 providers
配置項中注冊服務提供者
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
3.生成配置文件
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
此命令會在 config
目錄下生成 jwt.php
配置文件
4.生成密鑰
php artisan jwt:secret
此命令會在你的 .env
文件中新增一行 JWT_SECRET=secret
5.創建模型
php artisan make:model Models/User
代碼:
<?php namespace App\Models; use Tymon\JWTAuth\Contracts\JWTSubject; use Illuminate\Foundation\Auth\User as Authenticatable; class User extends Authenticatable implements JWTSubject { protected $fillable = ['name', 'password']; protected $hidden = ['password', 'remember_token']; // public function getJWTIdentifier() { return $this->getKey(); } public function getJWTCustomClaims() { return []; } }
6.修改配置文件 auth.php
'guards' => [ 'api' => [ 'driver' => 'jwt', 'provider' => 'users', 'hash' => false, ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class ], ],
7.實現登錄注冊返回token
php artisan make:controller Api/UserController
<?php namespace App\Http\Controllers\Api; use App\Http\Controllers\Controller; use App\Models\Member; use Illuminate\Http\Request; use Illuminate\Support\Facades\Hash; class PassportController extends Controller { public function __construct() { $this->middleware('auth:api', ['except' => ['register', 'login']]); } /** * 用戶注冊 */ public function register(Request $request) { // jwt token $credentials = [ 'name' => $request->name, 'password' => Hash::make($request->password) ]; $user = User::create($credentials); if($user){ $token = = JWTAuth::fromUser($user); return $this->responseWithToken($token); } } /** * 用戶登錄 */ public function login(Request $request) { // todo 用戶登錄邏輯 // jwt token $credentials = $request->only('name', 'password'); if (!$token = JWTAuth::attempt($credentials)) { return response()->json(['result'=>'failed']); } return $this->responseWithToken($token); } /** * 刷新token */ public function refresh() { return $this->responseWithToken(JWTAuth::refresh()); } /** * 退出登錄 */ public function logout(Request $request) { JWTAuth::logout(); } /** * 響應 */ private function responseWithToken(string $token) { $response = [ 'access_token' => $token, 'token_type' => 'Bearer', 'expires_in' => JWTAuth::factory()->getTTL() * 60 ]; return response()->json($response); } }
原文地址:https://www.stephen520.cn/blog/10255