| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379 |
- <?php
- namespace App\Module\OpenAPI\Validators;
- use UCore\Validator;
- use App\Module\OpenAPI\Models\OpenApiApp;
- use App\Module\OpenAPI\Enums\AUTH_TYPE;
- /**
- * 认证验证器
- *
- * 用于验证认证相关的数据
- */
- class AuthValidator extends Validator
- {
- /**
- * 验证应用认证信息
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- public function validateAppAuth(array $authData, string $arg): void
- {
- if (!isset($authData['app_id']) || empty($authData['app_id'])) {
- $this->addError($arg, '应用ID不能为空');
- return;
- }
- if (!isset($authData['auth_type']) || empty($authData['auth_type'])) {
- $this->addError($arg, '认证类型不能为空');
- return;
- }
- // 验证认证类型
- $authType = $authData['auth_type'];
- $validAuthTypes = array_column(AUTH_TYPE::cases(), 'value');
- if (!in_array($authType, $validAuthTypes)) {
- $this->addError($arg, '无效的认证类型');
- return;
- }
- // 根据认证类型验证相应的认证信息
- switch ($authType) {
- case AUTH_TYPE::API_KEY->value:
- $this->validateApiKeyAuth($authData, $arg);
- break;
- case AUTH_TYPE::OAUTH2->value:
- $this->validateOAuth2Auth($authData, $arg);
- break;
- case AUTH_TYPE::JWT->value:
- $this->validateJwtAuth($authData, $arg);
- break;
- case AUTH_TYPE::SIGNATURE->value:
- $this->validateSignatureAuth($authData, $arg);
- break;
- case AUTH_TYPE::BASIC->value:
- $this->validateBasicAuth($authData, $arg);
- break;
- case AUTH_TYPE::BEARER->value:
- $this->validateBearerAuth($authData, $arg);
- break;
- }
- }
- /**
- * 验证API Key认证
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- protected function validateApiKeyAuth(array $authData, string $arg): void
- {
- if (!isset($authData['app_secret']) || empty($authData['app_secret'])) {
- $this->addError($arg, 'API密钥不能为空');
- return;
- }
- $appId = $authData['app_id'];
- $appSecret = $authData['app_secret'];
- // 验证应用ID格式
- if (strlen($appId) !== 32 || !ctype_alnum($appId)) {
- $this->addError($arg, '应用ID格式错误');
- return;
- }
- // 验证应用密钥格式
- if (strlen($appSecret) !== 64 || !ctype_alnum($appSecret)) {
- $this->addError($arg, '应用密钥格式错误');
- return;
- }
- // 验证应用是否存在且有效
- $app = OpenApiApp::where('app_id', $appId)->first();
- if (!$app) {
- $this->addError($arg, '应用不存在');
- return;
- }
- if ($app->app_secret !== $appSecret) {
- $this->addError($arg, '应用密钥错误');
- return;
- }
- if (!$app->isActive()) {
- $this->addError($arg, '应用未激活或已被禁用');
- return;
- }
- }
- /**
- * 验证OAuth2认证
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- protected function validateOAuth2Auth(array $authData, string $arg): void
- {
- if (!isset($authData['access_token']) || empty($authData['access_token'])) {
- $this->addError($arg, '访问令牌不能为空');
- return;
- }
- $accessToken = $authData['access_token'];
- // 验证访问令牌格式(这里简化处理,实际应该调用OAuth服务验证)
- if (strlen($accessToken) < 32) {
- $this->addError($arg, '访问令牌格式错误');
- return;
- }
- // TODO: 调用OAuth模块验证令牌有效性
- // $oauthService = app(OAuthService::class);
- // if (!$oauthService->validateToken($accessToken)) {
- // $this->addError($arg, '访问令牌无效或已过期');
- // return;
- // }
- }
- /**
- * 验证JWT认证
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- protected function validateJwtAuth(array $authData, string $arg): void
- {
- if (!isset($authData['token']) || empty($authData['token'])) {
- $this->addError($arg, 'JWT令牌不能为空');
- return;
- }
- $token = $authData['token'];
- // 验证JWT令牌格式
- $parts = explode('.', $token);
- if (count($parts) !== 3) {
- $this->addError($arg, 'JWT令牌格式错误');
- return;
- }
- try {
- // 验证JWT令牌(这里简化处理,实际应该使用JWT库验证)
- foreach ($parts as $part) {
- $decoded = base64_decode($part, true);
- if ($decoded === false) {
- $this->addError($arg, 'JWT令牌格式错误');
- return;
- }
- }
- // TODO: 使用JWT库验证令牌签名和有效期
- // $jwt = app(JWTService::class);
- // if (!$jwt->validate($token)) {
- // $this->addError($arg, 'JWT令牌无效或已过期');
- // return;
- // }
- } catch (\Exception $e) {
- $this->addError($arg, 'JWT令牌验证失败');
- }
- }
- /**
- * 验证签名认证
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- protected function validateSignatureAuth(array $authData, string $arg): void
- {
- $requiredFields = ['timestamp', 'nonce', 'signature'];
- foreach ($requiredFields as $field) {
- if (!isset($authData[$field]) || empty($authData[$field])) {
- $this->addError($arg, "缺少必需的签名参数: {$field}");
- return;
- }
- }
- $timestamp = $authData['timestamp'];
- $nonce = $authData['nonce'];
- $signature = $authData['signature'];
- // 验证时间戳
- if (!is_numeric($timestamp)) {
- $this->addError($arg, '时间戳格式错误');
- return;
- }
- // 检查时间戳是否在合理范围内(5分钟内)
- $currentTime = time();
- $timeDiff = abs($currentTime - $timestamp);
- if ($timeDiff > 300) {
- $this->addError($arg, '请求时间戳过期');
- return;
- }
- // 验证随机数
- if (strlen($nonce) < 8) {
- $this->addError($arg, '随机数长度不足');
- return;
- }
- // 验证签名格式
- if (strlen($signature) !== 64 || !ctype_xdigit($signature)) {
- $this->addError($arg, '签名格式错误');
- return;
- }
- // TODO: 验证签名正确性
- // $app = OpenApiApp::where('app_id', $authData['app_id'])->first();
- // if ($app) {
- // $expectedSignature = $this->generateSignature($authData, $app->app_secret);
- // if (!hash_equals($expectedSignature, $signature)) {
- // $this->addError($arg, '签名验证失败');
- // return;
- // }
- // }
- }
- /**
- * 验证Basic认证
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- protected function validateBasicAuth(array $authData, string $arg): void
- {
- if (!isset($authData['username']) || empty($authData['username'])) {
- $this->addError($arg, '用户名不能为空');
- return;
- }
- if (!isset($authData['password']) || empty($authData['password'])) {
- $this->addError($arg, '密码不能为空');
- return;
- }
- $username = $authData['username'];
- $password = $authData['password'];
- // 验证用户名格式(应该是应用ID)
- if (strlen($username) !== 32 || !ctype_alnum($username)) {
- $this->addError($arg, '用户名格式错误');
- return;
- }
- // 验证密码格式(应该是应用密钥)
- if (strlen($password) !== 64 || !ctype_alnum($password)) {
- $this->addError($arg, '密码格式错误');
- return;
- }
- // 验证应用信息
- $app = OpenApiApp::where('app_id', $username)->first();
- if (!$app) {
- $this->addError($arg, '应用不存在');
- return;
- }
- if ($app->app_secret !== $password) {
- $this->addError($arg, '认证失败');
- return;
- }
- if (!$app->isActive()) {
- $this->addError($arg, '应用未激活或已被禁用');
- return;
- }
- }
- /**
- * 验证Bearer认证
- *
- * @param array $authData
- * @param string $arg
- * @return void
- */
- protected function validateBearerAuth(array $authData, string $arg): void
- {
- if (!isset($authData['token']) || empty($authData['token'])) {
- $this->addError($arg, 'Bearer令牌不能为空');
- return;
- }
- $token = $authData['token'];
- // 验证令牌格式
- if (strlen($token) < 32) {
- $this->addError($arg, 'Bearer令牌格式错误');
- return;
- }
- // TODO: 验证令牌有效性
- // 这里可以根据实际需求验证令牌是否有效
- // 可能需要查询数据库或调用其他服务
- }
- /**
- * 验证应用状态
- *
- * @param OpenApiApp $app
- * @param string $arg
- * @return void
- */
- public function validateAppStatus(OpenApiApp $app, string $arg): void
- {
- if (!$app->isActive()) {
- $this->addError($arg, '应用未激活或已被禁用');
- return;
- }
- if ($app->isExpired()) {
- $this->addError($arg, '应用已过期');
- return;
- }
- if ($app->isSuspended()) {
- $this->addError($arg, '应用已被暂停');
- return;
- }
- }
- /**
- * 验证权限范围
- *
- * @param OpenApiApp $app
- * @param string $requiredScope
- * @param string $arg
- * @return void
- */
- public function validateScope(OpenApiApp $app, string $requiredScope, string $arg): void
- {
- $appScopes = $app->scopes ?? [];
- if (empty($appScopes)) {
- $this->addError($arg, '应用没有配置权限范围');
- return;
- }
- // 检查是否有管理员权限
- if (in_array('ADMIN', $appScopes) || in_array('*', $appScopes)) {
- return;
- }
- // 检查是否有所需权限
- if (!in_array($requiredScope, $appScopes)) {
- $this->addError($arg, "缺少必需的权限范围: {$requiredScope}");
- return;
- }
- }
- }
|