155 lines
4.8 KiB
PHP
155 lines
4.8 KiB
PHP
<?php
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace App\Middleware\Auth;
|
||
|
||
use App\Constants\HttpEnumCode;
|
||
use App\Model\User;
|
||
use App\Utils\Auth;
|
||
use App\Utils\Jwt;
|
||
use Hyperf\Context\Context;
|
||
use Hyperf\HttpMessage\Stream\SwooleStream;
|
||
use Hyperf\HttpServer\Contract\RequestInterface;
|
||
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
|
||
use Hyperf\Redis\Redis;
|
||
use Psr\Container\ContainerInterface;
|
||
use Psr\Http\Message\ResponseInterface;
|
||
use Psr\Http\Message\ServerRequestInterface;
|
||
use Psr\Http\Server\MiddlewareInterface;
|
||
use Psr\Http\Server\RequestHandlerInterface;
|
||
|
||
class AuthMiddleware implements MiddlewareInterface
|
||
{
|
||
/**
|
||
* @var ContainerInterface
|
||
*/
|
||
protected ContainerInterface $container;
|
||
|
||
protected HttpResponse $response;
|
||
|
||
protected RequestInterface $request;
|
||
|
||
public function __construct(ContainerInterface $container, HttpResponse $response, RequestInterface $request)
|
||
{
|
||
$this->container = $container;
|
||
$this->response = $response;
|
||
$this->request = $request;
|
||
}
|
||
|
||
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||
{
|
||
$redis = $this->container->get(Redis::class);
|
||
$path_info = $this->request->getPathInfo();
|
||
$method = $this->request->getMethod();
|
||
|
||
$Auth = new Auth();
|
||
$Jwt = new Jwt();
|
||
|
||
// 获取token
|
||
$token = $this->getHeaderToken();
|
||
|
||
// 检测接口是否为免鉴权接口
|
||
$white_api = $Auth->checkApiWhiteList($path_info, $method);
|
||
|
||
if (!empty($token)){
|
||
if ($white_api){
|
||
// 存在token,免鉴权
|
||
$res = $redis->get('jwt_black_' . $token);
|
||
if ($res && time() >= $res) {
|
||
// token存在黑名单中
|
||
return $handler->handle($request);
|
||
}
|
||
|
||
// jwt验证
|
||
try {
|
||
$result = $Jwt->decode($token);
|
||
}catch (\Throwable $e) {
|
||
return $handler->handle($request);
|
||
}
|
||
}else{
|
||
// 存在token,鉴权
|
||
$res = $redis->get('jwt_black_' . $token);
|
||
if ($res && time() >= $res) {
|
||
// token存在黑名单中
|
||
return $this->response->json(fail(HttpEnumCode::HTTP_PROHIBIT));
|
||
}
|
||
|
||
// jwt验证
|
||
$result = $Jwt->decode($token);
|
||
|
||
// 处理即将过期token
|
||
$req = $Auth->checkTokenExpTime($result);
|
||
if ($req) {
|
||
// 即将过期,重新下发token
|
||
$new_token = $Jwt->encode($result['userInfo']);
|
||
|
||
// 旧token加入黑名单 5天有效期,5天内,无法继续进行访问
|
||
$res = $redis->set('jwt_black_' . $token, $result['exp'], 30);
|
||
if (!$res) {
|
||
// 添加缓存失败
|
||
return $this->response->json(fail(HttpEnumCode::SERVER_ERROR));
|
||
}
|
||
|
||
$response = Context::get(ResponseInterface::class);
|
||
$response = $response->withHeader('Authorization', $new_token);
|
||
Context::set(ResponseInterface::class, $response);
|
||
}
|
||
}
|
||
}else{
|
||
if ($white_api){
|
||
// token为空,免鉴权
|
||
return $handler->handle($request);
|
||
}else{
|
||
// token为空,鉴权
|
||
return $this->response->json(fail(HttpEnumCode::TOKEN_ERROR));
|
||
}
|
||
}
|
||
|
||
if (empty($result)){
|
||
return $this->response->json(fail(HttpEnumCode::SERVER_ERROR));
|
||
}
|
||
|
||
// 检测用户状态
|
||
$params = array();
|
||
$params['user_id'] = $result['userInfo']['user_id'];
|
||
$user = User::getOne($params);
|
||
if (empty($user)){
|
||
return $this->response->json(fail(HttpEnumCode::USER_STATUS_ERROR));
|
||
}
|
||
|
||
if ($user['user_status'] == 0){
|
||
return $this->response->json(fail(HttpEnumCode::USER_STATUS_DISABLE));
|
||
}
|
||
|
||
if ($user['user_status'] != 1){
|
||
return $this->response->json(fail(HttpEnumCode::USER_STATUS_ERROR));
|
||
}
|
||
|
||
$request = $this->request->withAttribute('userInfo', $result['userInfo']);
|
||
|
||
$request = Context::set(ServerRequestInterface::class, $request);
|
||
|
||
return $handler->handle($request);
|
||
}
|
||
|
||
/**
|
||
* 获取header中的token
|
||
* @return string
|
||
*/
|
||
protected function getHeaderToken(): string
|
||
{
|
||
$bearer_token = $this->request->getHeader('Authorization');
|
||
if (empty($bearer_token)){
|
||
return "";
|
||
}
|
||
|
||
// 解析token
|
||
$token = explode(' ', $bearer_token[0]);
|
||
|
||
return $token[1] ?? "";
|
||
}
|
||
|
||
|
||
}
|