使用服务账号凭证认证REST API时的AccessToken获取问题
解决方法
方案1:使用Google Cloud PHP官方库(推荐)
直接通过官方库生成令牌,完全避开shell_exec带来的环境、权限问题,且更稳定可靠。
- 先安装依赖:
composer require google/cloud-core
- 编写代码获取访问令牌:
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可能未正确加载 gcloudCLI不在Web进程的PATH中,或进程无执行权限gcloud命令需要交互式操作(如首次授权),但shell_exec是非交互式环境
内容的提问来源于stack exchange,提问作者Conor Cassidy
相关产品推荐
相关产品推荐

