使用服务账号认证Google Drive API PHP遇unauthorized_client错误求助
解决Google Drive API服务账号认证与文件可见性问题
问题根源分析
你遇到的两个问题是紧密关联的:
- 调用
$client->setSubject('xxx@xxx.com')时触发unauthorized_client错误:这是因为服务账号没有被授予域范围API委派权限,无法模拟指定用户执行操作。setSubject()是服务账号专门用于模拟Google Workspace/G Suite域内用户的方法,必须提前完成权限配置才能生效。 - 移除
setSubject()后文件在用户Drive UI不可见:此时服务账号是以自身身份创建文件,这些文件默认存储在服务账号的独立存储空间中,自然不会出现在普通用户的Drive界面里。
解决方案选择
根据你的账号类型(是否属于Google Workspace/G Suite域名),可以选择以下两种方案:
方案1:配置域范围委派(仅适用于Google Workspace/G Suite用户)
这是最彻底的解决方式,让服务账号直接模拟目标用户创建文件,文件会直接归属到用户的Drive中:
- 步骤1:启用服务账号的域范围委派
登录Google Cloud控制台,找到你的项目 → 进入「IAM与管理员」→「服务账号」→ 选中目标服务账号 → 点击「编辑」→ 展开「显示域范围委派」→ 勾选「启用G Suite域范围委派」并保存。 - 步骤2:在Workspace管理控制台授权
登录Google Workspace管理控制台 → 进入「安全」→「API控制」→「域范围委派」→ 点击「添加新的委派」:- 输入服务账号的客户端ID(可在Cloud控制台服务账号详情页找到)
- 添加权限范围:
https://www.googleapis.com/auth/drive(可根据实际需求调整) - 保存配置
- 步骤3:验证代码
此时你原来的代码就能正常运行,创建的文件会直接出现在xxx@xxx.com用户的Drive界面中。
方案2:共享文件或使用共享文件夹(适用于非Workspace用户)
如果不是Workspace用户,无法配置域范围委派,可以通过共享机制让用户看到文件:
- 方式A:创建文件后共享给目标用户
服务账号创建文件后,调用Drive API的权限接口,将文件共享给xxx@xxx.com:$driveService = new \Google_Service_Drive($client); // 创建文件(存储在服务账号自身空间) $fileMetadata = new \Google_Service_Drive_DriveFile(['name' => 'My Test File']); $file = $driveService->files->create($fileMetadata); // 给目标用户添加文件权限 $permission = new \Google_Service_Drive_Permission([ 'type' => 'user', 'role' => 'writer', // 可根据需求设置为owner/reader 'emailAddress' => 'xxx@xxx.com' ]); $driveService->permissions->create($file->id, $permission, ['sendNotificationEmail' => false]); - 方式B:创建文件到用户共享的文件夹
- 让目标用户在自己的Drive中创建一个文件夹,将该文件夹共享给服务账号的邮箱(格式为
[服务账号ID]@[项目ID].iam.gserviceaccount.com) - 服务账号创建文件时,指定该文件夹ID作为父目录:
这样文件会直接出现在用户的共享文件夹中,无需额外执行共享操作。$driveService = new \Google_Service_Drive($client); $fileMetadata = new \Google_Service_Drive_DriveFile([ 'name' => 'My Test File', 'parents' => ['用户共享的文件夹ID'] // 替换为实际文件夹ID ]); $file = $driveService->files->create($fileMetadata); - 让目标用户在自己的Drive中创建一个文件夹,将该文件夹共享给服务账号的邮箱(格式为
内容的提问来源于stack exchange,提问作者SakuragiRokurota
相关产品推荐
相关产品推荐

