使用 JWT 方式來實現 API 多使用者多表認證
1、先使用 composer
安裝 jwt-auth
執行下面命令
composer require "tymon/jwt-auth 1.*@rc"
2、laravel版本大於等於5.5版本可以省略此步驟 註冊服務提供者 config/app.php
'providers' => [
Tymon\JWTAuth\Providers\LaravelServiceProvider::class,
]
'aliases' => [
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',\
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
]
3、釋出生成配置檔案
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
4、使用以下命令生成金鑰
php artisan jwt:secret
5、配置多guard
來區分認證 開啟 config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // 預設是 token
'provider' => 'users',
],
// 新增admins 模組
'admin' => [
'driver' => 'jwt',
'provider' => 'admins',
]
],
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => App\Models\User::class,
],
'admins' => [
'driver' => 'eloquent',
'model' => App\Models\Admin::class,
]
],
6、生成相應的資料表 執行下面命令 php artisan make:model Models/Admin -m
生成 model 與對應的表
Schema::create('admins', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
7、執行 php artisan migrate
生成表結構, 執行下面 sql 語句生成資料
# users 表
insert into `users` ( `name`, `email`, `password`, `remember_token`, `created_at`, `updated_at`) values ( 'test123', '994914376@qq.com', '$2y$10$52EQECqdeemEXGoAs9u4iO4gN3CmtC0OY/8snDUEweANw4BQZbiCe', 'z9prihuBKigCGtaEA0GMp6TcyLnFTICUW4F5fuIK6RnZl2o7RC4HQ7BkPOBm', '2019-06-25 03:39:48', '2019-06-25 03:39:48');
# admins 表
insert into `admins` ( `name`, `email`, `password`, `remember_token`, `created_at`, `updated_at`) values ( 'Harvey Jenkins', 'mdouglas@example.com', '$2y$10$DVjo80fNjiPP1qlsW1eRsem9iwXNsClhFgZPQAp47flRUxyk8l/HG', 'XQmmqzC91R', '2019-06-25 05:06:18', '2019-06-25 05:06:18');
8、更改相應的 Model
檔案
App\Models\User
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* 獲取會儲存到 jwt 宣告中的標識
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* 返回包含要新增到 jwt 宣告中的自定義鍵值對陣列
* @return array
*/
public function getJWTCustomClaims()
{
return ['role' => 'user'];
}
}
App\Models\Admin
<?php
namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class Admin extends Authenticatable implements JWTSubject
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* 獲取會儲存到 jwt 宣告中的標識
* @return mixed
*/
public function getJWTIdentifier()
{
return $this->getKey();
}
/**
* 返回包含要新增到 jwt 宣告中的自定義鍵值對陣列
* @return array
*/
public function getJWTCustomClaims()
{
return ['role' => 'admin'];
}
}
9、在 router/api.php
檔案中建立路由資訊
# 普通使用者登入
Route::group(['prefix' => 'auth'], function () {
Route::post('login', 'AuthController@login');
Route::post('logout', 'AuthController@logout');
Route::post('refresh', 'AuthController@refresh');
Route::post('me', 'AuthController@me')->name('me')->middleware(['jwt.role:user', 'jwt.auth']);
});
# 後臺使用者登入
Route::group(['prefix' => 'admin', 'namespace' => 'Admin'], function () {
Route::post('login', 'LoginController@login');
Route::post('logout', 'LoginController@logout');
Route::post('refresh', 'LoginController@refresh');
Route::post('me', 'LoginController@me')->middleware(['jwt.role:admin', 'jwt.auth'])->name('me');
});
10、建立相應的控制器
AuthController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
class AuthController extends Controller
{
public function __construct()
{
$this->middleware('auth:api', ['except' => ['login']]);
}
/**
* @return JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function me()
{
return response()->json(auth('api')->user());
}
public function logout()
{
auth('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* @param $token
* @return JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
Admin/LoginController.php
<?php
namespace App\Http\Controllers\Admin;
use Illuminate\Http\JsonResponse;
use App\Http\Controllers\Controller;
class LoginController extends Controller
{
public function __construct()
{
$this->middleware('auth:admin', ['except' => ['login']]);
}
/**
* @return JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth('admin')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
public function me()
{
return response()->json(auth('admin')->user());
}
public function logout()
{
auth('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* @param $token
* @return JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
11、建立中介軟體檢測當前 token
對應的是哪個平臺 php artisan make:middleware JWTRoleAuth
<?php
namespace App\Http\Middleware;
use Closure;
use Tymon\JWTAuth\Exceptions\JWTException;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
class JWTRoleAuth extends BaseMiddleware
{
/**
* JWT 檢測當前登入的平臺
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param null $role
* @return mixed
*/
public function handle($request, Closure $next, $role = null)
{
try {
// 解析token角色
$tokenRole = $this->auth->parseToken()->getClaim('role');
} catch (JWTException $e) {
/**
* token解析失敗,說明請求中沒有可用的token。
* 為了可以全域性使用(不需要token的請求也可通過),這裡讓請求繼續。
* 因為這個中介軟體的責職只是校驗token裡的角色。
*/
return $next($request);
}
// 判斷token角色。
if ($tokenRole != $role) {
throw new UnauthorizedHttpException('jwt-auth', 'User role error');
}
return $next($request);
}
}
12、使用 postman
測試介面
13、到此 jwt
多使用者 多表認證就已經完成,如有問題和建議可以留言交流
注:以上的一些方式是直接參考網上的部份然後進行整理