| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- <?php
- namespace App\Module\OpenAPI\Services;
- use App\Module\OpenAPI\Models\OpenApiApp;
- use App\Module\OpenAPI\Models\OpenApiScope;
- use App\Module\OpenAPI\Enums\SCOPE_TYPE;
- use Illuminate\Support\Facades\Cache;
- use Illuminate\Support\Facades\Log;
- /**
- * 权限范围服务
- *
- * 提供API权限范围管理和验证功能
- */
- class ScopeService
- {
- /**
- * 检查应用是否具有指定权限
- *
- * @param OpenApiApp $app
- * @param string $requiredScope
- * @return bool
- */
- public function hasScope(OpenApiApp $app, string $requiredScope): bool
- {
- // 获取应用的权限范围
- $appScopes = $this->getAppScopes($app);
- // 如果应用没有配置权限范围,拒绝访问
- if (empty($appScopes)) {
- return false;
- }
- // 检查是否有管理员权限(拥有所有权限)
- if (in_array('ADMIN', $appScopes)) {
- return true;
- }
- // 检查是否直接拥有所需权限
- if (in_array($requiredScope, $appScopes)) {
- return true;
- }
- // 检查通配符权限
- if (in_array('*', $appScopes)) {
- return true;
- }
- // 检查权限依赖关系
- return $this->checkScopeDependencies($appScopes, $requiredScope);
- }
- /**
- * 检查多个权限
- *
- * @param OpenApiApp $app
- * @param array $requiredScopes
- * @param bool $requireAll 是否需要全部权限,false表示只需要其中一个
- * @return bool
- */
- public function hasScopes(OpenApiApp $app, array $requiredScopes, bool $requireAll = true): bool
- {
- if ($requireAll) {
- // 需要全部权限
- foreach ($requiredScopes as $scope) {
- if (!$this->hasScope($app, $scope)) {
- return false;
- }
- }
- return true;
- } else {
- // 只需要其中一个权限
- foreach ($requiredScopes as $scope) {
- if ($this->hasScope($app, $scope)) {
- return true;
- }
- }
- return false;
- }
- }
- /**
- * 获取应用的权限范围
- *
- * @param OpenApiApp $app
- * @return array
- */
- public function getAppScopes(OpenApiApp $app): array
- {
- // 优先从缓存获取
- $cacheKey = "app_scopes:{$app->app_id}";
- $scopes = Cache::get($cacheKey);
- if ($scopes === null) {
- $scopes = $app->scopes ?? [];
-
- // 缓存权限信息
- Cache::put($cacheKey, $scopes, 3600); // 缓存1小时
- }
- return $scopes;
- }
- /**
- * 更新应用权限范围
- *
- * @param OpenApiApp $app
- * @param array $scopes
- * @return bool
- */
- public function updateAppScopes(OpenApiApp $app, array $scopes): bool
- {
- // 验证权限范围
- $validationResult = $this->validateScopes($scopes);
- if (!$validationResult['valid']) {
- Log::warning('Invalid scopes provided', [
- 'app_id' => $app->app_id,
- 'invalid_scopes' => $validationResult['invalid_scopes'],
- ]);
- return false;
- }
- // 更新应用权限
- $app->update(['scopes' => $scopes]);
- // 清除缓存
- $this->clearAppScopeCache($app->app_id);
- // 记录权限变更日志
- $this->logScopeChange($app, $scopes);
- return true;
- }
- /**
- * 验证权限范围
- *
- * @param array $scopes
- * @return array ['valid' => bool, 'invalid_scopes' => array]
- */
- public function validateScopes(array $scopes): array
- {
- $validScopes = $this->getAllValidScopes();
- $invalidScopes = [];
- foreach ($scopes as $scope) {
- if (!in_array($scope, $validScopes)) {
- $invalidScopes[] = $scope;
- }
- }
- return [
- 'valid' => empty($invalidScopes),
- 'invalid_scopes' => $invalidScopes,
- ];
- }
- /**
- * 获取所有有效的权限范围
- *
- * @return array
- */
- public function getAllValidScopes(): array
- {
- $scopes = array_column(SCOPE_TYPE::cases(), 'value');
-
- // 添加特殊权限
- $scopes[] = '*'; // 通配符权限
- $scopes[] = 'ADMIN'; // 管理员权限
- return $scopes;
- }
- /**
- * 获取权限范围的详细信息
- *
- * @param string $scope
- * @return array|null
- */
- public function getScopeInfo(string $scope): ?array
- {
- // 特殊权限处理
- if ($scope === '*') {
- return [
- 'name' => '全部权限',
- 'description' => '拥有所有API的访问权限',
- 'risk_level' => 'HIGH',
- 'category' => 'SPECIAL',
- ];
- }
- if ($scope === 'ADMIN') {
- return [
- 'name' => '管理员权限',
- 'description' => '拥有管理员级别的所有权限',
- 'risk_level' => 'CRITICAL',
- 'category' => 'SPECIAL',
- ];
- }
- // 从枚举中获取权限信息
- foreach (SCOPE_TYPE::cases() as $scopeType) {
- if ($scopeType->value === $scope) {
- return [
- 'name' => $scopeType->getLabel(),
- 'description' => $scopeType->getDescription(),
- 'risk_level' => $scopeType->getRiskLevel(),
- 'category' => $scopeType->getCategory(),
- ];
- }
- }
- return null;
- }
- /**
- * 检查权限依赖关系
- *
- * @param array $appScopes
- * @param string $requiredScope
- * @return bool
- */
- protected function checkScopeDependencies(array $appScopes, string $requiredScope): bool
- {
- // 权限依赖关系映射
- $dependencies = [
- 'USER_WRITE' => ['USER_READ'],
- 'GAME_WRITE' => ['GAME_READ'],
- 'ITEM_WRITE' => ['ITEM_READ'],
- 'FUND_WRITE' => ['FUND_READ'],
- 'TRADE_WRITE' => ['TRADE_READ'],
- 'ADMIN_WRITE' => ['ADMIN_READ'],
- ];
- // 如果需要的权限有依赖,检查是否满足依赖
- if (isset($dependencies[$requiredScope])) {
- foreach ($dependencies[$requiredScope] as $dependency) {
- if (!in_array($dependency, $appScopes)) {
- return false;
- }
- }
- }
- // 检查是否有更高级的权限包含所需权限
- $hierarchies = [
- 'USER_READ' => ['USER_WRITE', 'ADMIN'],
- 'USER_WRITE' => ['ADMIN'],
- 'GAME_READ' => ['GAME_WRITE', 'ADMIN'],
- 'GAME_WRITE' => ['ADMIN'],
- 'ITEM_READ' => ['ITEM_WRITE', 'ADMIN'],
- 'ITEM_WRITE' => ['ADMIN'],
- 'FUND_READ' => ['FUND_WRITE', 'ADMIN'],
- 'FUND_WRITE' => ['ADMIN'],
- 'TRADE_READ' => ['TRADE_WRITE', 'ADMIN'],
- 'TRADE_WRITE' => ['ADMIN'],
- ];
- if (isset($hierarchies[$requiredScope])) {
- foreach ($hierarchies[$requiredScope] as $higherScope) {
- if (in_array($higherScope, $appScopes)) {
- return true;
- }
- }
- }
- return false;
- }
- /**
- * 清除应用权限缓存
- *
- * @param string $appId
- * @return void
- */
- protected function clearAppScopeCache(string $appId): void
- {
- $cacheKey = "app_scopes:{$appId}";
- Cache::forget($cacheKey);
- }
- /**
- * 记录权限变更日志
- *
- * @param OpenApiApp $app
- * @param array $newScopes
- * @return void
- */
- protected function logScopeChange(OpenApiApp $app, array $newScopes): void
- {
- $oldScopes = $app->getOriginal('scopes') ?? [];
- Log::info('App scopes updated', [
- 'app_id' => $app->app_id,
- 'old_scopes' => $oldScopes,
- 'new_scopes' => $newScopes,
- 'added_scopes' => array_diff($newScopes, $oldScopes),
- 'removed_scopes' => array_diff($oldScopes, $newScopes),
- ]);
- }
- /**
- * 获取权限范围的分组信息
- *
- * @return array
- */
- public function getScopeGroups(): array
- {
- $groups = [];
- foreach (SCOPE_TYPE::cases() as $scope) {
- $category = $scope->getCategory();
- if (!isset($groups[$category])) {
- $groups[$category] = [
- 'name' => $category,
- 'scopes' => [],
- ];
- }
- $groups[$category]['scopes'][] = [
- 'value' => $scope->value,
- 'label' => $scope->getLabel(),
- 'description' => $scope->getDescription(),
- 'risk_level' => $scope->getRiskLevel(),
- ];
- }
- return $groups;
- }
- }
|