2018/5/7
- 說實話,官方文件也是相當的亂,這次根據文件並檢視原始碼實驗了很多地方,大改了一次。
2018/10/4
- 結合大家提出的問題和我近期新的理解,寫了一篇新文章,講的比較深,大家可以去看看 JWT 超詳細分析。本文這次主要修改了一些細節,對大家提出的問題整理寫到文章中。
本文是以 1.0.0-rc 為基準的。
JWT 全稱 JSON Web Tokens ,是一個非常輕巧的規範。這個規範允許我們使用JWT在使用者和伺服器之間傳遞安全可靠的資訊。它的兩大使用場景是:認證和資料交換。
資料
先擺出幾個參考資料,可以把連線都開啟,方便查閱:
Laravel
1. 使用 composer 安裝
# 建議使用1.0以上版本
composer require tymon/jwt-auth 1.*@rc
2. 進行一些配置
這裡值得注意的是,有些文件會說要新增 Tymon\JWTAuth\Providers\LaravelServiceProvider::class
,這隻在 Laravel 5.4 及以下版本是必要的,更新的 Laravel 版本無需新增。
還有一些文件說要新增 Tymon\JWTAuth\Providers\JWTAuthServiceProvider
這是很久以前的 JWT 版本的(大概0.5.3 以前的版本)。
2.1 釋出配置檔案
# 這條命令會在 config 下增加一個 jwt.php 的配置檔案
php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"
2.2 生成加密金鑰
# 這條命令會在 .env 檔案下生成一個加密金鑰,如:JWT_SECRET=foobar
php artisan jwt:secret
2.3 更新你的模型
如果你使用預設的 User 表來生成 token,你需要在該模型下增加一段程式碼
<?php
namespace App;
use Tymon\JWTAuth\Contracts\JWTSubject;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable implements JWTSubject # 這裡別忘了加
{
use Notifiable;
// Rest omitted for brevity
/**
* 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 [];
}
}
2.4 註冊兩個 Facade
這兩個 Facade 並不是必須的,但是使用它們會給你的程式碼編寫帶來一點便利。
config/app.php
'aliases' => [
...
// 新增以下兩行
'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory',
],
如果你不使用這兩個 Facade,你可以使用輔助函式 auth()
auth() 是一個輔助函式,返回一個guard,暫時可以看成 Auth Facade。
對於它有很多有必要說的,可以看我單獨寫的一篇文章——Laravel 輔助函式 auth 與 JWT 擴充套件詳解
// 如果你不用 Facade,你可以這麼寫
auth('api')->refresh();
// 用 JWTAuth Facade
JWTAuth::parseToken()->refresh();
兩個 Facede 常用可使用方法,可以看文章後面的附錄。
2.5 修改 auth.php
config/auth.php
'guards' => [
'web' => [
'driver' => 'session',
'provider' => 'users',
],
'api' => [
'driver' => 'jwt', // 原來是 token 改成jwt
'provider' => 'users',
],
],
2.6 註冊一些路由
注意:在 Laravel 下,route/api.php
中的路由預設都有字首 api
。
Route::group([
'prefix' => 'auth'
], function ($router) {
Route::post('login', 'AuthController@login');
Route::post('logout', 'AuthController@logout');
Route::post('refresh', 'AuthController@refresh');
Route::post('me', 'AuthController@me');
});
2.7 建立 token 控制器
php artisan make:controller AuthController
AuthController
值得注意的是 Laravel 這要用 auth('api')
,至於為什麼,我另一篇關於 JWT 擴充套件詳解的文章裡有講。
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\Auth;
use App\Http\Controllers\Controller;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
* 要求附帶email和password(資料來源users表)
*
* @return void
*/
public function __construct()
{
// 這裡額外注意了:官方文件樣例中只除外了『login』
// 這樣的結果是,token 只能在有效期以內進行重新整理,過期無法重新整理
// 如果把 refresh 也放進去,token 即使過期但仍在重新整理期以內也可重新整理
// 不過重新整理一次作廢
$this->middleware('auth:api', ['except' => ['login']]);
// 另外關於上面的中介軟體,官方文件寫的是『auth:api』
// 但是我推薦用 『jwt.auth』,效果是一樣的,但是有更加豐富的報錯資訊返回
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login()
{
$credentials = request(['email', 'password']);
if (! $token = auth('api')->attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
/**
* Get the authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json(auth('api')->user());
}
/**
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
auth('api')->logout();
return response()->json(['message' => 'Successfully logged out']);
}
/**
* Refresh a token.
* 重新整理token,如果開啟黑名單,以前的token便會失效。
* 值得注意的是用上面的getToken再獲取一次Token並不算做重新整理,兩次獲得的Token是並行的,即兩個都可用。
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken(auth('api')->refresh());
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => auth('api')->factory()->getTTL() * 60
]);
}
}
Lumen
1. 使用 composer 安裝
上面是用命令列安裝的,這裡用 composer.json 安裝。
// 我當時可用的版本是這個
"tymon/jwt-auth": "1.*@rc"
執行
composer update
2. 進行一些配置
2.1 開啟 Facade 和 Eloquent
取消以下行的註釋。
bootstrap/app.php
// $app->withFacades();
// $app->withEloquent();
2.2 開啟中介軟體認證
取消以下行的註釋。
bootstrap/app.php
// $app->routeMiddleware([
// 'auth' => App\Http\Middleware\Authenticate::class,
// ]);
// $app->register(App\Providers\AuthServiceProvider::class);
2.3 新增服務提供者
bootstrap/app.php
// 有些文件裡是說新增 Tymon\JWTAuth\Providers\JWTAuthServiceProvider::class,那是舊版本的
$app->register(\Tymon\JWTAuth\Providers\LumenServiceProvider::class);
2.4 生成加密金鑰
這條命令會在 .env 檔案下生成一個加密金鑰,如:JWT_SECRET=foobar
php artisan jwt:secret
2.5 更新你的模型
如果你使用預設的 User 表來生成 token,你需要在該模型下增加一段程式碼
<?php
namespace App;
use Illuminate\Auth\Authenticatable;
use Laravel\Lumen\Auth\Authorizable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Model implements AuthenticatableContract, AuthorizableContract, JWTSubject
{
use Authenticatable, Authorizable;
...
/**
* 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 [];
}
}
2.6 註冊兩個 Facade
Lumen 中沒有輔助函式 auth(),這兩個 Facade 就挺有用了。
bootstrap/app.php
把原先去了註釋的那一行再改一下。
$app->withFacades(true, [
'Tymon\JWTAuth\Facades\JWTAuth' => 'JWTAuth',
'Tymon\JWTAuth\Facades\JWTFactory' => 'JWTFactory',
]);
2.7 設定 auth.php
把 \vendor\laravel\lumen-framework\config\auth.php
也複製到 專案根目錄config
資料夾(沒有就新建)。
文件中有提到
Lumen 風格的配置檔案這個概念
指的就是都在 .env 檔案中設定各種設定項,在
\vendor\laravel\lumen-framework\config
資料夾下面的其他配置檔案中也可以看到,很多配置項都有env(設定項key, 預設值)
這個方法,有這個配置項的就可以在 .env 檔案中設定設定項=你的設定值
這樣設定。而複製到根目錄
config
資料夾是 Laravel 風格的配置檔案實現方式這裡我本來想盡量按 Lumen 風格實現的,但是下面這些屬性預設並沒有
env()
方式實現,所以我還是複製到根目錄下改算了。
auth.php
按下面進行新增或修改。
'guards' => [
'api' => [
'driver' => 'jwt',
'provider' => 'users',
],
],
...
'providers' => [
'users' => [
'driver' => 'eloquent',
'model' => \App\User::class
]
2.8 註冊一些路由
Route::group([
'prefix' => 'auth'
], function ($router) {
Route::post('login', 'AuthController@login');
Route::post('logout', 'AuthController@logout');
Route::post('refresh', 'AuthController@refresh');
Route::post('me', 'AuthController@me');
});
2.9 建立 token 控制器
Lumen 還精簡了很多輔助函式,比如 auth 和 bcrypt 等。
可以安裝 cosmicvelocity/lumen-helpers 或 albertcht/lumen-helpers 補全(建議用後者,更好安裝)
或者使用上面說的兩個 Facade。
AuthController.php
如果你沒使用擴充套件補充的輔助函式,你需要這麼寫,不然直接用上面的 Laravel 那個
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Facades\JWTAuth;
class AuthController extends Controller
{
/**
* Create a new AuthController instance.
*
* @return void
*/
public function __construct()
{
// 這裡額外注意了:官方文件樣例中只除外了『login』
// 這樣的結果是,token 只能在有效期以內進行重新整理,過期無法重新整理
// 如果把 refresh 也放進去,token 即使過期但仍在重新整理期以內也可重新整理
// 不過重新整理一次作廢
$this->middleware('auth:api', ['except' => ['login']]);
// 另外關於上面的中介軟體,官方文件寫的是『auth:api』
// 但是我推薦用 『jwt.auth』,效果是一樣的,但是有更加豐富的報錯資訊返回
}
/**
* Get a JWT via given credentials.
*
* @return \Illuminate\Http\JsonResponse
*/
public function login(Request $request)
{
$credentials = $request->only('email', 'password');
if (! $token = JWTAuth::attempt($credentials)) {
return response()->json(['error' => 'Unauthorized'], 401);
}
return $this->respondWithToken($token);
}
/**
* Get the authenticated User.
*
* @return \Illuminate\Http\JsonResponse
*/
public function me()
{
return response()->json(JWTAuth::parseToken()->touser());
}
/**
* Log the user out (Invalidate the token).
*
* @return \Illuminate\Http\JsonResponse
*/
public function logout()
{
JWTAuth::parseToken()->invalidate();
return response()->json(['message' => 'Successfully logged out']);
}
/**
* Refresh a token.
*
* @return \Illuminate\Http\JsonResponse
*/
public function refresh()
{
return $this->respondWithToken(JWTAuth::parseToken()->refresh());
}
/**
* Get the token array structure.
*
* @param string $token
*
* @return \Illuminate\Http\JsonResponse
*/
protected function respondWithToken($token)
{
return response()->json([
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => JWTAuth::factory()->getTTL() * 60
]);
}
}
關於中介軟體
1.0 版本以上的 jwt-auth,中介軟體在服務提供者中已經定義了,所以不需要額外寫,按上面來即可。
下面是可用的中介軟體,第一二個功能一樣,但是第二個不會丟擲錯誤,第三四個功能一樣,沒什麼區別。
tymon\jwt-auth\src\Providers\AbstractServiceProvider.php
protected $middlewareAliases = [
'jwt.auth' => Authenticate::class,
'jwt.check' => Check::class,
'jwt.refresh' => RefreshToken::class,
'jwt.renew' => AuthenticateAndRenew::class,
];
1. token 的獲取、使用、刪除和重新整理
- 以下用 postman 演示,
{{TEST}}
為 postman 全域性變數:test.yfree.ccc
- Laravel 環境下寫在 api.php 中的路由預設有字首 api
- 下面的圖是 Lumen 環境的,沒有預設區字首 api
1.1 獲取 token
獲取token
1.2 使用 token
有兩種使用方法:
- 加到 url 中:
?token=你的token
- 加到 header 中,建議用這種,因為在 https 情況下更安全:
Authorization:Bearer 你的token
使用 token
新增中介軟體保護的就需要使用 token進行訪問
可以使用的中介軟體有 auth、auth:api、jwt.auth、jwt.refresh、jwt.check、jwt.renew
關於這些中介軟體之間有什麼差別,可以看我的另一篇文章:Laravel 輔助函式 auth 與 JWT 擴充套件詳解
1.3 刪除 token
刪除 token
刪除 token
後,token就會失效,無法再利用其獲取資料。
1.4 重新整理 token
重新整理 token
重新整理後,舊 token 將會失效,但是你可以設定一個寬限時間,這個在後面具體說。
2. token 的組成、建立以及解析
2.1 組成
一個 JWT token 是一個字串,它由三部分組成,頭部、載荷與簽名,中間用 .
分隔,例如:xxxxx.yyyyy.zzzzz
頭部(header)
頭部通常由兩部分組成:令牌的型別(即JWT)和正在使用的簽名演算法(如HMAC SHA256 或 RSA.)。
例如:
{
"alg": "HS256",
"typ": "JWT"
}
然後用 Base64Url
編碼得到頭部,即 xxxxx
。
載荷(Payload)
載荷中放置了 token
的一些基本資訊,以幫助接受它的伺服器來理解這個 token
。同時還可以包含一些自定義的資訊,使用者資訊交換。
載荷的屬性也分三類:
- 預定義(Registered)
- 公有(public)
- 私有(private)
預定義的載荷
{
"sub": "1",
"iss": "http://localhost:8000/auth/login",
"iat": 1451888119,
"exp": 1454516119,
"nbf": 1451888119,
"jti": "37c107e4609ddbcc9c096ea5ee76c667",
"aud": "dev"
}
這裡面的前 7 個欄位都是由官方所定義的,也就是預定義(Registered claims)的,並不都是必需的。
- iss (issuer):簽發人
- sub (subject):主題
- aud (audience):受眾
- exp (expiration time):過期時間
- nbf (Not Before):生效時間,在此之前是無效的
- iat (Issued At):簽發時間
- jti (JWT ID):編號
公有的載荷
在使用 JWT 時可以額外定義的載荷。為了避免衝突,應該使用 IANA JSON Web Token Registry 中定義好的,或者給額外載荷加上類似名稱空間的唯一標識。
私有載荷
在資訊互動的雙方之間約定好的,既不是預定義載荷也不是公有載荷的一類載荷。這一類載荷可能會發生衝突,所以應該謹慎使用。
將上面的 json
進行 Base64Url
編碼得到載荷,,即 yyyyy
。
關於載荷的理解:
這裡三種載荷的定義應該明確的一點是 —— 對於後兩種載荷,它並非定義了載荷的種類,然後讓你去選用哪種載荷,而是對你可能會定義出來的載荷做一個分類。
比如你定義了一個
admin
載荷,這個載荷按其分類應該是私有載荷,可能會和其他人定義的發生衝突。但如果你加了一個字首(名稱空間),如namespace-admin
,那麼這應該就算一個公有載荷了。(但其實標準並沒有定義怎麼去宣告名稱空間,所以嚴格來說,還是可能會衝突)但是在現實中,團隊都是約定好的了要使用的載荷,這樣的話,好像根本不存在衝突的可能。那為什麼文件要這麼定義呢?我的理解是,RFC 是提出一種技術規範,出發點是一套通用的規範,考慮的範圍是所有開發者,而不僅僅侷限於一個開發者團隊。就像用 token 做認證已經是很常見的技術了,但是 JWT 的提出就相當於提出了一套較為通用的技術規範。既然是為了通用,那麼考慮在大環境下的衝突可能性也是必須的。
簽名(Signature)
簽名時需要用到前面編碼過的兩個字串,如果以 HMACSHA256
加密,就如下:
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret
)
加密後再進行 base64url
編碼最後得到的字串就是 token
的第三部分 zzzzz
。
組合便可以得到 token:xxxxx.yyyyy.zzzzz
。
簽名的作用:保證 JWT 沒有被篡改過,原理如下:
HMAC 演算法是不可逆演算法,類似 MD5 和 hash ,但多一個金鑰,金鑰(即上面的secret)由服務端持有,客戶端把 token 發給服務端後,服務端可以把其中的頭部和載荷再加上事先共享的 secret 再進行一次 HMAC 加密,得到的結果和 token 的第三段進行對比,如果一樣則表明資料沒有被篡改。
Hash-based Message Authentication Code
PHP 程式碼示例
// 這裡要開啟true
$zzzzz = $this->base64url_encode(hash_hmac('sha256', 'xxxxx.yyyyy', getenv('JWT_SECRET'), true));
protected function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
2.2 token 的建立
前面的 AuthController.php
中有兩行展現了這一種 token
的建立方法,即用使用者所給的賬號和密碼進行嘗試,密碼正確則用對應的 User
資訊返回一個 token
。
但 token
的建立方法不止這一種,接下來介紹 token
的三種建立方法:
- 基於賬密引數
- 基於 users 模型返回的例項
- 基於 users 模型中的使用者主鍵 id
a) 基於賬密引數
這就是剛剛說的哪一種,貼出具體程式碼。
// 使用輔助函式
$credentials = request(['email', 'password']);
$token = auth()->attempt($credentials)
// 使用 Facade
$credentials = $request->only('email', 'password');
$token = JWTAuth::attempt($credentials);
b) 基於 users 模型返回的例項
// 使用輔助函式
$user = User::first();
$token = auth()->login($user);
// 使用 Facade
$user = User::first();
$token = JWTAuth::fromUser($credentials);
c) 基於 users 模型中的主鍵 id
// 使用輔助函式
$token = auth()->tokenById(1);
// 使用 Facade
原始碼中沒找到
2.3 token 的解析
a) 解析 token 到物件
只有 Facade 需要這樣。
// 把請求傳送過來的直接解析到物件
JWTAuth::parseToken();
b) 獲取 token 中的 user 資訊
// 輔助函式
$user = auth()->user();
// Facade
$user = JWTAuth::parseToken()->authenticate();
c) 獲取 token
如果 token 被設定則會返回,否則會嘗試使用方法從請求中解析 token ,如果token未被設定或不能解析最終返回false。
// 輔助函式
$token = auth()->getToken();
// Facade
$token = JWTAuth::parseToken()->getToken();
更多方法可以看文章後面的附錄。
d) 如果是前端
直接 base64
解碼 token
的前兩段即可以知道所需的資訊。
3. 載荷的設定和獲取
a) 載荷設定
載荷資訊會在 token 解碼時得到,同時越大的陣列會生成越長的 token ,所以不建議放太多的資料。同時因為載荷是用 Base64Url
編碼,所以相當於明文,因此絕對不能放密碼等敏感資訊。
$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
// 輔助函式
$token = auth()->claims($customClaims)->attempt($credentials);
// Facade - 1
$token = JWTAuth::claims($customClaims)->attempt($credentials);
--- 下面兩種試了好像不行,不過前面的夠用了
// Facade - 2
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
// Facade - 3
$payload = JWTFactory::sub(123)->aud('foo')->foo(['bar' => 'baz'])->make();
$token = JWTAuth::encode($payload);
b) 載荷解析
從請求中把載荷解析出來。可以去看擴充套件原始碼,裡面還有很多的方法。
// 輔助函式
$exp = auth()->payload()->get('exp');
$json = auth()->payload()->toJson();
$array = auth()->payload()->jsonSerialize();
$sub = $array['sub'];
// Facade - 1
$payload = JWTAuth::parseToken()->getPayload();
$payload->get('sub'); // = 123
$payload['jti']; // = 'asfe4fq434asdf'
$payload('exp') // = 123456
$payload->toArray(); // = ['sub' => 123, 'exp' => 123456, 'jti' => 'asfe4fq434asdf'] etc
// Facade - 2
$exp = JWTAuth::parseToken()->getClaim('exp');
4. token 的三個時間
一個 token
一般來說有三個時間屬性,其配置都在 config/jwt.php 內。
有效時間
有效時間指的的是你獲得 token
後,在多少時間內可以憑這個 token
去獲取內容,逾時無效。
// 單位:分鐘
'ttl' => env('JWT_TTL', 60)
重新整理時間
重新整理時間指的是在這個時間內可以憑舊 token
換取一個新 token
。例如 token
有效時間為 60 分鐘,重新整理時間為 20160 分鐘,在 60 分鐘內可以透過這個 token
獲取新 token
,但是超過 60 分鐘是不可以的,然後你可以一直迴圈獲取,直到總時間超過 20160 分鐘,不能再獲取。
這裡過期後能否重新整理,經 [@Rootrl](https://learnku.com/users/433) 指出,其實並不是這麼絕對,具體細節,看我們上面 AuthController 處的程式碼。有詳細補充
這也是一個 token 被加入黑名單之後,會存在的時間
// 單位:分鐘
'refresh_ttl' => env('JWT_REFRESH_TTL', 20160)
寬限時間
寬限時間是為了解決併發請求的問題,假如寬限時間為 0s ,那麼在新舊 token
交接的時候,併發請求就會出錯,所以需要設定一個寬限時間,在寬限時間內,舊 token
仍然能夠正常使用。
// 寬限時間需要開啟黑名單(預設是開啟的),黑名單保證過期token不可再用,最好開啟
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true)
// 設定寬限時間,單位:秒
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 60)
5. 關於 JWT 的討論
5.1 為什麼用 JWT?
看我的新文章 JWT 超詳細分析 。
5.2 token 的重新整理問題?
a) token 為什麼要重新整理嗎?
首先 Basic Auth
是一種最簡單的認證方法,但是由於每次請求都帶使用者名稱和密碼,頻繁的傳輸肯定不安全,所以才有 cookies
和 session
的運用。如果 token
不重新整理,那麼 token
就相當於上面的使用者名稱+密碼,只要獲取到了,就可以一直盜用,因此 token
設定有效期並能夠進行重新整理是必要的。
b) token 有效期多久合適,重新整理頻率多久合適?
有效期越長,風險性越高,有效性越短,重新整理頻率越高,重新整理就會存在重新整理開銷,所以這需要綜合考慮。而且 web 端應該設定為分鐘級和小時級,而移動端應該設定為天級和周級。
c) 有沒有必要每次都重新整理 token ?
看我的新文章 JWT 超詳細分析 。
1. JWT 的 兩個 Facade
1.1 JWTAuth
JWTAuth::parseToken()->方法()
一般都可以換成 auth()->方法()
。
token 生成
attempt
根據 user 賬密新建一個 token。
$credentials = $request->only('email', 'password');
$token = JWTAuth::attempt($credentials);
fromUser or fromSubject
根據 user 物件生成一個 token。後者是前者別名。
$user = User::find(1);
$token = JWTAuth::fromUser($user);
token 控制
refresh
更新 token。
$newToken = JWTAuth::parseToken()->refresh();
invalidate
讓一個 token 無效。
JWTAuth::parseToken()->invalidate();
check
檢驗 token 的有效性。
if(JWTAuth::parseToken()->check()) {
dd("token是有效的");
}
token 解析
authenticate or toUser or user
這三個效果是一樣的,toUser
是 authenticate
的別名,而 user
比前兩者少一個 user id 的校驗,但並沒有什麼影響。
$user = JWTAuth::parseToken()->toUser();
parseToken
從 request 中解析 token 到物件中,以便進行下一步操作。
JWTAuth::parseToken();
getToken
從 request 中獲取token。
$token = JWTAuth::getToken(); // 這個不用 parseToken ,因為方法內部會自動執行一次
載荷控制
customClaims or claims
設定載荷的 customClaims 部分。後者是前者的別名。
$customClaims = ['sid' => $sid, 'code' => $code];
$credentials = $request->only('email', 'password');
$token = JWTAuth::customClaims($customClaims)->attempt($credentials);
getCustomClaims
獲取載荷的 customClaims 部分,返回一個陣列。
$customClaims = JWTAuth::parseToken()->getCustomClaims()
getPayload or payload
獲取所有載荷,三個都是一樣的,最後一個一般用來檢驗 token 的有效性
$payload = JWTAuth::parseToken()->payload();
// then you can access the claims directly e.g.
$payload->get('sub'); // = 123
$payload['jti']; // = 'asfe4fq434asdf'
$payload('exp') // = 123456
$payload->toArray(); // = ['sub' => 123, 'exp' => 123456, 'jti' => 'asfe4fq434asdf'] etc
getClaim
獲取載荷中指定的一個元素。
$sub = JWTAuth::parseToken()->getClaim('sub');
1.2 JWTGuard
這個 Facade 主要進行載荷的管理,返回一個載荷物件,然後可以透過 JWTAuth 來對其生成一個 token。
// 載荷的高度自定義
$payload = JWTFactory::sub(123)->aud('foo')->foo(['bar' => 'baz'])->make();
$token = JWTAuth::encode($payload);
$customClaims = ['foo' => 'bar', 'baz' => 'bob'];
$payload = JWTFactory::make($customClaims);
$token = JWTAuth::encode($payload);
1.3 其他一些用法
這裡用 auth 的寫法,因為 Laravel 有多個 guard,預設 guard 也不是 api ,所以需要寫成 auth('api')
否則,auth()
即可。
設定載荷
$token = auth('api')->claims(['foo' => 'bar'])->attempt($credentials);
顯示設定 token
$user = auth('api')->setToken('eyJhb...')->user();
顯示設定請求
$user = auth('api')->setRequest($request)->user();
重寫有效時間
$token = auth('api')->setTTL(7200)->attempt($credentials);
驗證賬密是否正確
$boolean = auth('api')->validate($credentials);
本作品採用《CC 協議》,轉載必須註明作者和本文連結