composer require phper666/jwt-auth
<?php
declare(strict_types=1);
namespace App\Middleware;
use Phper666\JwtAuth\Jwt;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Phper666\JwtAuth\Exception\TokenValidException;
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
class JwtAuthMiddleware implements MiddlewareInterface
{
/**
* @var HttpResponse
*/
protected $response;
protected $prefix = 'Bearer';
protected $jwt;
public function __construct(HttpResponse $response, Jwt $jwt)
{
$this->response = $response;
$this->jwt = $jwt;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$isValidToken = false;
$token = $request->getHeader('Authorization')[0] ?? '';
if (strlen($token) > 0) {
$token = ucfirst($token);
$arr = explode($this->prefix . ' ', $token);
$token = $arr[1] ?? '';
try{
if (strlen($token) > 0 && $this->jwt->checkToken()) {
$isValidToken = true;
}
}catch(\Exception $e){
$data = [
'code' => 401,
'msg' => '對不起,token驗證沒有通過',
'data' => [],
];
return $this->response->json($data);
}
}
if ($isValidToken) {
return $handler->handle($request);
}
$data = [
'code' => 401,
'msg' => '對不起,token驗證沒有通過',
'data' => [],
];
return $this->response->json($data);
}
}
<?php
declare(strict_types = 1);
namespace App\Controller\Auth;
use App\Model\User;
use Phper666\JwtAuth\Jwt;
use App\Controller\Controller;
use Hyperf\Di\Annotation\Inject;
class LoginController extends Controller
{
/**
* @Inject
*
* @var Jwt
*/
protected $jwt;
/**
* 使用者登入.
*
* @return array
*/
public function login()
{
// $hash = password_hash($this->request->input('password'), PASSWORD_DEFAULT);
// return $this->failed($hash);
$user = User::query()->where('account', $this->request->input('account'))->first();
//驗證使用者賬戶密碼
if (!empty($user->password) && password_verify($this->request->input('password'), $user->password)) {
$userData = [
'uid' => $user->id,
'account' => $user->account,
];
$token = $this->jwt->getToken($userData);
$data = [
'token' => (string) $token,
'exp' => $this->jwt->getTTL(),
];
return $this->success($data);
}
return $this->failed('登入失敗');
}
}
<?php
declare(strict_types=1);
namespace App\Controller;
use App\Model\User;
use Phper666\JwtAuth\Jwt;
use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Hyperf\Elasticsearch\ClientBuilderFactory;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Task\TaskExecutor;
use Hyperf\Utils\Coroutine;
use Hyperf\Task\Task;
use App\Task\MethodTask;
use Hyperf\Server\ServerFactory;
class UserController extends Controller
{
/**
* @Inject()
* @var Jwt
*/
protected $jwt;
/**
* @Inject()
* @var ValidatorFactoryInterface
*/
protected $validationFactory;
/**
* 獲取使用者資訊
* @return [type] [description]
*/
public function info()
{
//獲取token中的使用者資料
$user = $this->jwt->getParserData();
$userInfo = User::query()->where('account', $user['account'])->get();
return $this->success($userInfo);
}
/**
* 使用者退出
* @return [type] [description]
*/
public function logout()
{
if ($this->jwt->logout()) {
return $this->success('','退出登入成功');
};
return $this->failed('退出登入失敗');
}
}
<?php
declare(strict_types = 1);
namespace App\Controller;
use Hyperf\Di\Annotation\Inject;
use Psr\Container\ContainerInterface;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
class Controller
{
/**
* @Inject
*
* @var ContainerInterface
*/
protected $container;
/**
* @Inject
*
* @var RequestInterface
*/
protected $request;
/**
* @Inject
*
* @var ResponseInterface
*/
protected $response;
/**
* 請求成功
*
* @param $data
* @param string $message
*
* @return array
*/
public function success($data, $message = 'success')
{
$code = $this->response->getStatusCode();
return ['msg' => $message, 'code' => $code, 'data' => $data];
}
/**
* 請求失敗.
*
* @param string $message
*
* @return array
*/
public function failed($message = 'Request format error!')
{
return ['msg' => $message, 'code' => 500, 'data' => ''];
}
}
<?php
declare(strict_types=1);
return [
# 登入方式,sso為單點登入,mpop為多點登入
'login_type' => env('JWT_LOGIN_TYPE', 'sso'),
# 單點登入自定義資料中必須存在uid的鍵值,這個key你可以自行定義,只要自定義資料中存在該鍵即可
'sso_key' => 'uid',
# 非對稱加密使用字串,請使用自己加密的字串
'secret' => env('JWT_SECRET', 'phper666'),
/*
* JWT 許可權keys
* 對稱演算法: HS256, HS384 & HS512 使用 `JWT_SECRET`.
* 非對稱演算法: RS256, RS384 & RS512 / ES256, ES384 & ES512 使用下面的公鑰私鑰.
*/
'keys' => [
# 公鑰,例如:'file://path/to/public/key'
'public' => env('JWT_PUBLIC_KEY'),
# 私鑰,例如:'file://path/to/private/key'
'private' => env('JWT_PRIVATE_KEY'),
],
# token過期時間,單位為秒
'ttl' => env('JWT_TTL', 7200),
# jwt的hearder加密演算法
'alg' => env('JWT_ALG', 'HS256'),
# 是否開啟黑名單,單點登入和多點登入的登出、重新整理使原token失效,必須要開啟黑名單,目前黑名單快取只支援hyperf快取驅動
'blacklist_enabled' => env('JWT_BLACKLIST_ENABLED', true),
# 黑名單的寬限時間 單位為:秒,注意:如果使用單點登入,該寬限時間無效
'blacklist_grace_period' => env('JWT_BLACKLIST_GRACE_PERIOD', 0),
# 黑名單快取token時間,注意:該時間一定要設定比token過期時間要大,預設為1天
'blacklist_cache_ttl' => env('JWT_BLACKLIST_CACHE_TTL', 86400),
];
Router::post('/user/login', 'App\Controller\Auth\LoginController@login');
Router::post('/user/register', 'App\Controller\Auth\RegisterController@register');
//個人資料
Router::addGroup('/user/', function () {
Router::get('info','App\Controller\UserController@info');
Router::post('logout', 'App\Controller\UserController@logout');
Router::get('elasticsearch', 'App\Controller\UserController@elasticsearch');
}, [
'middleware' => [App\Middleware\JwtAuthMiddleware::class]
]);
接下來可以模擬API請求,看效果