AuthorizeMiddleware.php 3.2 KB
Newer Older
秦俊坤's avatar
秦俊坤 committed
1 2 3 4
<?php

namespace Meibuyu\Micro\Middleware;

秦俊坤's avatar
秦俊坤 committed
5 6 7
use FastRoute\Dispatcher;
use Hyperf\HttpServer\Router\DispatcherFactory;
use Hyperf\Utils\ApplicationContext;
秦俊坤's avatar
秦俊坤 committed
8 9 10 11 12 13
use Meibuyu\Micro\Model\Auth;
use Meibuyu\Micro\Service\Interfaces\User\AuthenticationServiceInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
秦俊坤's avatar
秦俊坤 committed
14
use Hyperf\Di\Annotation\Inject;
秦俊坤's avatar
秦俊坤 committed
15 16 17 18 19 20 21 22 23 24 25 26

class AuthorizeMiddleware implements MiddlewareInterface
{

    /**
     * @Inject()
     * @var AuthenticationServiceInterface
     */
    private $authorizationService;

    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
    {
秦俊坤's avatar
秦俊坤 committed
27
        $path = $request->getUri()->getPath();
秦俊坤's avatar
秦俊坤 committed
28 29
        $token = token();
        $applicationName = env('APP_NAME');
秦俊坤's avatar
秦俊坤 committed
30
        $method = $request->getMethod();
秦俊坤's avatar
秦俊坤 committed
31

秦俊坤's avatar
秦俊坤 committed
32 33 34
        if (empty($path)) return $handler->handle($request);
        //获取对应的 path 对应的权限,如果 path 是不需要登录鉴权,直接返回
        $passed  = $this->authRouter($applicationName, $path, $method, $token);
秦俊坤's avatar
秦俊坤 committed
35 36 37 38
        if ($passed)  {
            return $handler->handle($request);
        }

秦俊坤's avatar
秦俊坤 committed
39 40 41 42 43
        return response()->withStatus(403)->json(
            [
                'code' => 403,
                'msg' => "您没有访问接口的权限,请检查后再操作"
            ]);     //鉴权失败,错误码 403 forbidden
秦俊坤's avatar
秦俊坤 committed
44
        //path 是需要登录鉴权的,判断当前用户是佛有对应  path 的权限
秦俊坤's avatar
秦俊坤 committed
45 46 47 48 49 50 51 52 53 54 55

    }


    /**
     * 获取对应路由的权限,调用 RPC 服务
     * @param $applicationName
     * @param $route
     * @param $token
     * @return bool
     */
秦俊坤's avatar
秦俊坤 committed
56
    protected function authRouter($applicationName, $path, $method, $token):  bool
秦俊坤's avatar
秦俊坤 committed
57 58
    {
        $userId = $this->getUserIdByToken($token);
秦俊坤's avatar
秦俊坤 committed
59 60
        $route = $this->getRouterByPath($path, $method);
        if (empty($route)) return true;     //说明没有匹配到路由,直接 pass,后续执行一定会返回 404, 这里也可以直接  返回 404
秦俊坤's avatar
秦俊坤 committed
61

秦俊坤's avatar
秦俊坤 committed
62
        return $this->authorizationService->authByRouter($applicationName, $route, $method, $userId);
秦俊坤's avatar
秦俊坤 committed
63 64
    }

秦俊坤's avatar
秦俊坤 committed
65 66 67 68 69 70
    /**
     * 根据 path 和 method 获取对应的 router
     * @param string $path
     * @param string $method
     * @return array|string
     */
秦俊坤's avatar
秦俊坤 committed
71
    private function getRouterByPath(string $path, string $method) : string
秦俊坤's avatar
秦俊坤 committed
72 73 74 75 76 77 78 79 80 81
    {
        $factory = ApplicationContext::getContainer()->get(DispatcherFactory::class);
        $dispatcher = $factory->getDispatcher('http');
        $routerMatched = $dispatcher->dispatch($method, $path);
        $founded =  $routerMatched[0];
        if ( $founded != Dispatcher::FOUND) return '';        //说明没有匹配上路由,可以直接 return 404 not found

        $handler = $routerMatched[1];
        return $handler->route;
    }
秦俊坤's avatar
秦俊坤 committed
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97

    /**
     * 根据 token 获取对应的 user_id
     * @param $token
     * @return int|mixed
     */
    protected function getUserIdByToken($token)
    {
        if (empty($token)) return 0;
        $user = redis()->get($token);
        if ( ! $user)  return 0;

        $userArr =   \json_decode($user, true);
        return !empty($userArr['id']) ? $userArr['id'] : 0;
    }
}