Refresh Token7天过期原因及Laravel谷歌云盘上传异常解决方案咨询
Google Drive API Refresh Token 7天过期问题解决方案
问题背景
我基于Laravel开发了一个集成Google Drive API的存储应用,目前遇到Refresh Token每7天自动过期的问题,导致云盘上传功能中断,需要部署到生产环境解决这个问题。我尝试了以下代码,希望实现AccessToken/Refresh Token过期时自动处理,但问题仍未解决:
public function uploadFile(UploadedFile $uploadedFile, string $file,string $folderId) { $client = new Google_Client(); $client->setClientId(env('GOOGLE_DRIVE_CLIENT_ID')); $client->setClientSecret(env('GOOGLE_DRIVE_CLIENT_SECRET')); $client->refreshToken(env('GOOGLE_DRIVE_REFRESH_TOKEN')); $this->refreshTokenIfNeeded($client); $fileName = $uploadedFile->getClientOriginalName(); $mimeType = $uploadedFile->getClientMimeType(); $fileContent = file_get_contents($uploadedFile); $fileMetadata = new Google_Service_Drive_DriveFile(array( 'name' => $fileName, 'parents' => array($folderId) )); //file upload code } public function refreshTokenIfNeeded(Google_Client $client): void { if ($client->isAccessTokenExpired()) { $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); $newAccessToken = $client->getAccessToken(); $this->saveAccessTokenToStorage($newAccessToken); } else { $oldAccessToken = $client->getAccessToken(); $this->saveAccessTokenToStorage($oldAccessToken); } } public function saveAccessTokenToStorage($newAccessToken): void { $accessTokenJson = json_encode($newAccessToken); $credentialsFilePath = env('GOOGLE_CREDENTIALS_FILE'); Storage::put("$credentialsFilePath", $accessTokenJson); }
核心原因
Google OAuth 2.0规则明确:未经过Google验证的第三方应用,其生成的Refresh Token会在7天后自动过期,这是平台的安全限制。当前代码仅处理了AccessToken过期的情况,完全没覆盖Refresh Token本身过期的场景。
可行解决方案
1. 切换为服务账号(生产环境首选)
服务账号是Google专为服务器端后台操作设计的身份,无需用户授权,也不存在Refresh Token过期问题:
- 登录Google Cloud控制台,创建服务账号并下载JSON密钥文件,将文件存到Laravel的
storage/app目录下 - 修改客户端初始化代码:
public function uploadFile(UploadedFile $uploadedFile, string $folderId) { $client = new Google_Client(); // 加载服务账号密钥 $client->setAuthConfig(storage_path('app/google-service-account.json')); $client->addScope(Google_Service_Drive::DRIVE_FILE); $client->setAccessType('offline'); $driveService = new Google_Service_Drive($client); $fileName = $uploadedFile->getClientOriginalName(); $mimeType = $uploadedFile->getClientMimeType(); $fileContent = file_get_contents($uploadedFile); $fileMetadata = new Google_Service_Drive_DriveFile([ 'name' => $fileName, 'parents' => [$folderId] ]); // 执行上传并返回文件ID $file = $driveService->files->create($fileMetadata, [ 'data' => $fileContent, 'mimeType' => $mimeType, 'uploadType' => 'multipart', 'fields' => 'id' ]); return $file->getId(); }
- 登录Google Drive,把目标上传文件夹共享给服务账号的邮箱(密钥文件里的
client_email字段),授予编辑权限。
2. 提交应用进行Google验证(适合需用户授权的场景)
如果业务必须保留用户授权流程,需要将应用提交Google官方验证,通过后Refresh Token会变为长期有效:
- 进入Google Cloud控制台的OAuth consent screen页面,完善应用的基本信息、隐私政策链接等内容
- 提交验证申请,等待Google审核(通常需要数天到数周)
- 验证通过后,Refresh Token不会再自动过期(除非用户主动撤销授权)
3. 优化代码错误处理(临时应急方案)
如果暂时无法切换服务账号或完成验证,需在代码中捕获Refresh Token过期的异常,触发重新授权逻辑:
public function refreshTokenIfNeeded(Google_Client $client): void { try { if ($client->isAccessTokenExpired()) { $newToken = $client->fetchAccessTokenWithRefreshToken($client->getRefreshToken()); // 检查是否成功获取新token,失败则说明refresh token已过期 if (!isset($newToken['access_token'])) { throw new \Exception('Refresh Token已过期,请重新授权'); } $this->saveAccessTokenToStorage($newToken); } else { $this->saveAccessTokenToStorage($client->getAccessToken()); } } catch (\Google_Service_Exception $e) { // 捕获Google API返回的invalid_grant错误(refresh token无效) if (str_contains($e->getMessage(), 'invalid_grant')) { throw new \Exception('Refresh Token已过期,请重新授权'); } // 其他异常原样抛出 throw $e; } }
在上传方法中捕获该异常后,可引导用户重新完成OAuth授权流程,获取新的Refresh Token。
内容的提问来源于stack exchange,提问作者Reshma Gawade
相关产品推荐
相关产品推荐

