PermAnnotationAspect.php 3.44 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
<?php
/**
 * Created by PhpStorm.
 * User: Zero
 * Date: 2020/4/8
 * Time: 14:48
 */

namespace Meibuyu\Micro\Aspect;

11
use Hyperf\Contract\ConfigInterface;
12 13 14 15 16
use Hyperf\Di\Annotation\Aspect;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Di\Aop\AbstractAspect;
use Hyperf\Di\Aop\ProceedingJoinPoint;
use Hyperf\Utils\Str;
17
use Meibuyu\Micro\Annotation\AutoPerm;
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
use Meibuyu\Micro\Annotation\Perm;
use Meibuyu\Micro\Exceptions\HttpResponseException;
use Meibuyu\Micro\Handler\PermHandler;

/**
 * @Aspect()
 */
class PermAnnotationAspect extends AbstractAspect
{

    /**
     * @Inject()
     * @var PermHandler
     */
    private $permHandler;

34 35 36 37 38 39
    /**
     * @Inject
     * @var ConfigInterface
     */
    protected $config;

40 41
    public $annotations = [
        Perm::class,
42
        AutoPerm::class,
43 44 45 46 47 48 49 50 51 52
    ];

    /**
     * @param ProceedingJoinPoint $proceedingJoinPoint
     * @return mixed
     * @throws HttpResponseException
     * @throws \Hyperf\Di\Exception\Exception
     */
    public function process(ProceedingJoinPoint $proceedingJoinPoint)
    {
53 54 55 56 57 58 59
        $perm = $this->genPermName($proceedingJoinPoint);
        if ($perm) {
            if ($this->permHandler->check($perm)) {
                return $proceedingJoinPoint->process();
            } else {
                throw new HttpResponseException('当前用户没有此操作权限');
            }
60
        }
61
        return $proceedingJoinPoint->process();
62 63
    }

64 65
    // 生成权限名
    public function genPermName(ProceedingJoinPoint $proceedingJoinPoint)
66
    {
67 68 69
        /** @var AutoPerm $autoPerm */
        /** @var Perm $perm */
        [$autoPerm, $perm] = $this->getAnnotations($proceedingJoinPoint);
王源's avatar
王源 committed
70 71 72 73
        $className = $proceedingJoinPoint->className;
        $methodName = $proceedingJoinPoint->methodName;
        if ($autoPerm && in_array($methodName, $autoPerm->exclude)) {
            return false; // 跳过不需要鉴权的方法
74
        }
王源's avatar
王源 committed
75 76 77
        $prefix = $autoPerm && $autoPerm->prefix ? $autoPerm->prefix : $this->genPrefix($className);
        $name = $perm && $perm->name ? $perm->name : $this->genName($methodName);
        return $this->parsePermName($prefix, $name);
78 79
    }

80
    // 拼接权限名
王源's avatar
王源 committed
81
    protected function parsePermName($prefix, $name)
82 83
    {
        // 注意每个应用的app_name的唯一性
王源's avatar
王源 committed
84 85 86 87
        $appName = trim($this->config->get('app_name'), '_');
        $prefix = trim($prefix, '_');
        $name = trim($name, '_');
        return $appName . '_' . $prefix . '_' . $name;
88 89 90 91
    }

    // 生成前缀
    protected function genPrefix(string $className): string
92 93
    {
        $handledNamespace = Str::replaceFirst('Controller', '', Str::after($className, '\\Controller\\'));
94 95 96
        $namespaceLength = strrpos($handledNamespace, '\\');
        $prefix = $namespaceLength ? substr($handledNamespace, $namespaceLength + 1) : $handledNamespace;
        $prefix = Str::snake($prefix);
97 98 99 100
        $prefix = str_replace('__', '_', $prefix);
        return $prefix;
    }

王源's avatar
王源 committed
101 102
    // 生成名称
    protected function genName(string $methodName): string
王源's avatar
王源 committed
103
    {
王源's avatar
王源 committed
104 105 106
        $methodName = Str::snake($methodName);
        $methodName = str_replace('__', '_', $methodName);
        return $methodName;
王源's avatar
王源 committed
107 108
    }

109 110
    // 获取注解
    public function getAnnotations(ProceedingJoinPoint $proceedingJoinPoint)
111 112
    {
        $metadata = $proceedingJoinPoint->getAnnotationMetadata();
113 114 115 116
        return [
            $metadata->class[AutoPerm::class] ?? null,
            $metadata->method[Perm::class] ?? null
        ];
117 118 119
    }

}