2023-02-17 17:10:16 +08:00

155 lines
4.8 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?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] ?? "";
}
}