關於JWT 可以參考 JWT 完整使用詳解 這裡說一下在實際專案中的使用:
laravel 5.5
php7.1
"tymon/jwt-auth": "1.*@rc"
JWT token
的重新整理 和 基於 JWT 實現單使用者登陸
理解
使用者登陸後 獲取到 tokenA
(這個時候 tokenA
的有效期是60分鐘)
透過 tokenA
獲取到 tokenB
(這個時候 tokenB
的有效期是60分鐘,tokenA
開始進行 60秒的 倒數計時,60秒後就會被拉黑)
tokenB
換取 tokenC
(成功後 tokenB
開始進行60秒倒數計時,60秒後會被拉黑)
env
配置如下:
JWT_SECRET=jbSn01PbHsFoRzEqHtuOsM3rV3FCsGcI
JWT_BLACKLIST_ENABLED=true # 是否開啟toekn黑名單 生產環境需要開啟 寬限時間需要開啟黑名單(預設是開啟的),黑名單保證過期token不可再用,最好開啟
JWT_BLACKLIST_GRACE_PERIOD=60 # 設定寬限時間,單位:秒
JWT_REFRESH_TTL=20160 # 重新整理時間 單位:分鐘
JWT_TTL=60 # 有效時間 單位:分鐘
基於 JWT token
的單使用者登陸, 在 token
的載荷配置中做一點手腳即可:
<?php
namespace App\Http\Controllers;
use Auth;
use App\Business\UserBusiness;
use App\Transformers\UserTransformer;
use Illuminate\Http\Request;
use Tymon\JWTAuth\Facades\JWTAuth;
use Tymon\JWTAuth\Facades\JWTFactory;
/**
* 使用者相關
*
* @Resource("user", uri="/api")
*/
class UserController extends Controller
{
protected $userBusiness;
/**
* UserController constructor.
* @param UserBusiness $userBusiness
*/
public function __construct(UserBusiness $userBusiness)
{
$this->userBusiness = $userBusiness;
}
/**
* 使用者登陸
*
* 使用 `username` 和 `password` 進行登陸。
*
* @Post("/login")
* @Versions({"v1"})
* @Transaction({
* @Request({"username": "foo", "password": "bar"}),
* @Response(200, body={"code":1,"time":"2018-08-10 09:32:44","message":"success","data":{"access_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOlwvXC9hcGkuc21hcnR2aWRlby5jb21cL2FwaVwvbG9naW4iLCJpYXQiOjE1MzM4NjQ3NjQsImV4cCI6MTUzMzg2ODM2NCwibmJmIjoxNTMzODY0NzY0LCJqdGkiOiJsZTJObzRLVDZlT0NyVnZCIiwic3ViIjoiZGVkZjYyZTI5MDA0MTFlODgzM2I1NGVlNzVlNTM1MzciLCJwcnYiOiI4N2UwYWYxZWY5ZmQxNTgxMmZkZWM5NzE1M2ExNGUwYjA0NzU0NmFhIn0.OdJlE_pUuttqIxsjKF-FAcZOhMYitS69fh18lPZAYmQ","token_type":"bearer","expires_in":3600}}),
* @Response(200, body=
* {
* "message": "使用者不存在",
* "code": 4000,
* "status_code": 500
* }
* )
*
* })
*/
public function login(Request $request)
{
$rules = [
'username' => 'required',
'password' => 'required'
];
$this->_validate($request, $rules);
$spbill_create_ip = $request->header('x-real-ip')?: $request->ip();
iLog('----------spbill_create_ip------------'. $spbill_create_ip);
$username = $request->username;
$password = $request->password;
$login_time = time();
$user = $this->userBusiness->dologin($username,$password,$spbill_create_ip,$login_time);
// Get the token
$factory = JWTFactory::customClaims([
'sub' => $user->guid,
'ip' => $spbill_create_ip,
'login_time' => $login_time
]);
$payload = $factory->make();
$token = JWTAuth::encode($payload);
return $this->_response($this->respondWithToken((string)$token));
}
protected function respondWithToken($token)
{
return [
'access_token' => $token,
'token_type' => 'bearer',
'expires_in' => JWTAuth::factory()->getTTL() * 60
];
}
}
<?php
namespace App\Http\Middleware;
use App\Business\ResponseException;
use App\Common\ResponseCode;
use Closure;
use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
class ClientCheck extends BaseMiddleware
{
/**
* @param $request
* @param Closure $next
* @return mixed
* @throws ResponseException
*/
public function handle($request, Closure $next)
{
$array = $this->auth->payload()->jsonSerialize();
$user = $this->auth->user();
if (key_exists('ip',$array) && key_exists('login_time',$array)) {
if ($array['ip'] != $user->ip || $array['login_time'] != $user->login_at) throw new ResponseException("該賬戶已在其他裝置登陸",ResponseCode::OTHER_CLIENT_LOGIN);
}
return $next($request);
}
}
本作品採用《CC 協議》,轉載必須註明作者和本文連結