You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用服务账号凭证认证REST API时的AccessToken获取问题

解决方法

方案1:使用Google Cloud PHP官方库(推荐)

直接通过官方库生成令牌,完全避开shell_exec带来的环境、权限问题,且更稳定可靠。

  1. 先安装依赖:
composer require google/cloud-core
  1. 编写代码获取访问令牌:
use Google\Auth\ApplicationDefaultCredentials;
use Google\Auth\HttpHandler\Guzzle6HttpHandler;
use GuzzleHttp\Client;

// 基于已设置的GOOGLE_APPLICATION_CREDENTIALS环境变量初始化凭证
$credentials = ApplicationDefaultCredentials::getCredentials(
    'https://www.googleapis.com/auth/cloud-platform' // 匹配Gen App Builder所需的权限范围
);

// 创建HTTP处理实例
$httpHandler = new Guzzle6HttpHandler(new Client());
// 获取令牌
$tokenResult = $credentials->fetchAuthToken($httpHandler);

// 提取可用的access token
$accessToken = $tokenResult['access_token'];

方案2:手动调用Google OAuth2令牌端点

如果不想引入第三方库,可以纯PHP实现JWT签名并请求令牌:

// 读取服务账号密钥文件
$serviceAccountKey = json_decode(file_get_contents(getenv('GOOGLE_APPLICATION_CREDENTIALS')), true);

// 构造JWT头部与载荷
$header = json_encode(['alg' => 'RS256', 'typ' => 'JWT']);
$payload = json_encode([
    'iss' => $serviceAccountKey['client_email'],
    'scope' => 'https://www.googleapis.com/auth/cloud-platform',
    'aud' => 'https://oauth2.googleapis.com/token',
    'exp' => time() + 3600, // 令牌有效期1小时
    'iat' => time()
]);

// Base64URL编码工具函数
function base64UrlEncode($data) {
    return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
$encodedHeader = base64UrlEncode($header);
$encodedPayload = base64UrlEncode($payload);

// 使用服务账号私钥签名
openssl_sign(
    "$encodedHeader.$encodedPayload",
    $signature,
    $serviceAccountKey['private_key'],
    OPENSSL_ALGO_SHA256
);
$encodedSignature = base64UrlEncode($signature);

// 构造完整JWT
$jwt = "$encodedHeader.$encodedPayload.$encodedSignature";

// 请求令牌
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://oauth2.googleapis.com/token');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
    'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
    'assertion' => $jwt
]));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);

$tokenData = json_decode($response, true);
$accessToken = $tokenData['access_token'] ?? null;

补充:shell_exec失败的常见原因

  • Web服务器进程(如www-data)的环境变量与你手动执行时不一致,GOOGLE_APPLICATION_CREDENTIALS可能未正确加载
  • gcloud CLI不在Web进程的PATH中,或进程无执行权限
  • gcloud命令需要交互式操作(如首次授权),但shell_exec是非交互式环境

内容的提问来源于stack exchange,提问作者Conor Cassidy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:25:16