Laravel5使用 Jwt-Auth 實現 API 使用者認證
阿新 • • 發佈:2018-12-28
jwt-auth 最新版本是 1.0.0 rc.1 版本,已經支援了 Laravel 5.5。如果你使用的是 Laravel 5.5 版本,可以使用如下命令安裝。
如果你是 Laravel 5.5 以下版本,也推薦使用最新版本,RC.1 前的版本都存在多使用者token認證的安全問題。
composer require tymon/jwt-auth 1.0.0-rc.1
新增服務提供商
將下面這行新增至 config/app.php
檔案 providers
陣列中:
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
將下面這行新增至 config/app.php
'JWTAuth'=> Tymon\JWTAuth\Facades\JWTAuth::class,
'JWTFactory'=> Tymon\JWTAuth\Facades\JWTFactory::class,
在你的 shell 中執行如下命令釋出 配置檔案:
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
此命令會在 config
目錄下生成一個 jwt.php
配置檔案,你可以在此進行自定義配置。
生成金鑰
php artisan jwt:secret
此命令會在你的 .env
檔案中新增一行 JWT_SECRET=secret
。
配置 Auth guard
在 config/auth.php
檔案中,你需要將 guards/driver
更新為 jwt
:
'defaults' => [ 'guard' => 'api', // 修改為api 'passwords' => 'users', ], 'guards' => [ 'api' => [ 'driver' => 'jwt', // JWTGuard 實現,原始碼中為 token,我這改成 jwt 了 'provider' => 'users', ], ], 'providers' => [ 'users' => [ 'driver' => 'eloquent', 'model' => App\Models\User::class, // 根據你model的位置更改 ], ],
更改 Model
如果需要使用 jwt-auth 作為使用者認證,我們需要對我們的 User
模型進行一點小小的改變,變更後的 User
模型如下:
<?php
namespace App\Models;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
protected $table = 'users';
protected $fillable = ['name', 'password', 'mobile'];
#定義是否預設維護時間,預設是true.改為false,則以下時間相關設定無效
public $timestamps = true;
protected $hidden = [
'password',
];
/**
* Get the identifier that will be stored in the subject claim of the JWT.
*
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* Return a key value array, containing any custom claims to be added to the JWT.
*
* @return array
*/
public function getJWTCustomClaims()
{
return [];
}
}
使用者提供賬號密碼前來登入。如果登入成功,那麼我會給前端頒發一個 access _token
執行如下命令以新建一箇中間件:
php artisan make:middleware ApiAuth
中介軟體程式碼 ApiAuth.php 如下:
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Exceptions\TokenExpiredException;
use Tymon\JWTAuth\Exceptions\TokenInvalidException;
use JWTAuth;
class ApiAuth
{
public function handle($request, Closure $next)
{
try {
if (! $user = JWTAuth::parseToken()->authenticate()) { //獲取到使用者資料,並賦值給$user
return response()->json([
'errcode' => 1004,
'errmsg' => 'user not found'
], 404);
}
return $next($request);
} catch (TokenExpiredException $e) {
return response()->json([
'errcode' => 1003,
'errmsg' => 'token 過期' , //token已過期
]);
} catch (TokenInvalidException $e) {
return response()->json([
'errcode' => 1002,
'errmsg' => 'token 無效', //token無效
]);
} catch (JWTException $e) {
return response()->json([
'errcode' => 1001,
'errmsg' => '缺少token' , //token為空
]);
}
}
}
在app\Http\Kernel.php下新增如下程式碼
protected $routeMiddleware = [
'api.auth' => \App\Http\Middleware\ApiAuth::class,
];
現在,我們可以在 routes/api.php
路由檔案中路由來測試一下
Route::post('login', '[email protected]');
Route::post('register', '[email protected]');
控制器程式碼如下:
use JWTAuth;
public function login(Request $request)
{
// 驗證規則,由於業務需求,這裡我更改了一下登入的使用者名稱,使用手機號碼登入
$rules = [
'mobile' => ['required'],
'password' => 'required|string|min:6|max:20',
];
// 驗證引數,如果驗證失敗,則會丟擲 ValidationException 的異常
$params = $this->validate($request, $rules);
// 使用 Auth 登入使用者,如果登入成功,則返回 201 的 code 和 token,如果登入失敗則返回
$token = JWTAuth::attempt($params);
if ($token) {
return $this->responseData(['access_token' => $token]);
} else {
$this->responseError('賬號或密碼錯誤');
}
}
public function register(RegisterRequest $request)
{
$mobile = $request->input('mobile');
$password = $request->input('password');
// 註冊使用者
$user = User::create([
'mobile' => $mobile,
'password' => bcrypt($password),
'nickname' => encryptedPhoneNumber($mobile)
]);
// 獲取token
$token = JWTAuth::fromUser($user);
if (!$token) {
return $this->responseError('註冊失敗,請重試');
}
return $this->responseData([
'access_token' => $token,
'user' => $user
]);
}
測試截圖如下: