PHP服务器通过REST调用Google API:服务账号是否需刷新令牌及获取方法
服务账号访问Google API的REST方式说明
嘿,刚好对这块熟,给你掰扯清楚:
首先明确一点:服务账号模式下完全不需要刷新令牌!
和咱们平时用的普通OAuth2授权码流程不一样,服务账号是通过生成**JWT(JSON Web Token)**来换取访问令牌的,访问令牌过期后直接重新生成新的就行,根本不需要刷新令牌这个环节——这是服务账号的核心特性之一,比普通流程少了一步维护刷新令牌的麻烦。
那具体怎么通过REST获取可用的访问令牌呢?给你一步步拆解:
1. 准备好服务账号密钥
先从Google Cloud控制台下载服务账号的JSON密钥文件,里面会包含client_email、private_key这两个关键字段,后面要用到。
2. 构造JWT内容
JWT分为Header、Payload、Signature三部分:
- Header:固定格式,指定签名算法为RS256:
{ "alg": "RS256", "typ": "JWT" } - Payload:需要包含这些必填字段:
iss:就是密钥里的client_emailscope:你要访问的API权限范围,比如访问Drive只读就填https://www.googleapis.com/auth/drive.readonly,多个scope用空格分隔aud:固定为https://oauth2.googleapis.com/tokenexp:令牌过期时间戳,建议设为当前时间+3600秒(1小时,Google允许的最长有效期)iat:当前时间戳(令牌生成时间)
3. 签名生成完整JWT
用密钥里的private_key对Header和Payload的Base64URL编码拼接后的字符串进行RS256签名,得到完整的JWT字符串。PHP里可以用openssl_sign函数来实现。
4. 发送请求换取访问令牌
向https://oauth2.googleapis.com/token发送POST请求,参数如下:
grant_type:固定值urn:ietf:params:oauth:grant-type:jwt-bearerassertion:刚才生成的完整JWT字符串
请求成功后,响应里会返回access_token,用这个令牌就可以调用对应的Google API了。
给你个PHP原生实现的示例片段
<?php // 加载服务账号密钥 $serviceAccountKey = json_decode(file_get_contents('path/to/your/service-account-key.json'), true); // 构造JWT Header $header = json_encode([ 'alg' => 'RS256', 'typ' => 'JWT' ]); // 构造JWT Payload $now = time(); $payload = json_encode([ 'iss' => $serviceAccountKey['client_email'], 'scope' => 'https://www.googleapis.com/auth/drive.readonly', 'aud' => 'https://oauth2.googleapis.com/token', 'exp' => $now + 3600, 'iat' => $now ]); // Base64URL编码工具函数 function base64UrlEncode($data) { return rtrim(strtr(base64_encode($data), '+/', '-_'), '='); } $encodedHeader = base64UrlEncode($header); $encodedPayload = base64UrlEncode($payload); // 拼接待签名的字符串 $signatureInput = $encodedHeader . '.' . $encodedPayload; // 生成签名 openssl_sign($signatureInput, $signature, $serviceAccountKey['private_key'], 'SHA256'); $encodedSignature = base64UrlEncode($signature); // 组装完整JWT $jwt = $encodedHeader . '.' . $encodedPayload . '.' . $encodedSignature; // 发送请求获取访问令牌 $ch = curl_init('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); // 拿到可用的access_token $accessToken = $tokenData['access_token']; ?>
额外注意事项
- 如果要访问Google Workspace(原G Suite)的用户资源,还需要在Workspace Admin控制台里给服务账号开启域范围授权(Domain-Wide Delegation),把服务账号的
client_id添加到授权列表,并指定对应的scope。 - 访问令牌有效期只有1小时,所以每次调用API前可以检查是否过期,或者干脆每次调用前都生成新的令牌——这个过程很轻量,不会有性能问题。
内容的提问来源于stack exchange,提问作者Scrabionau77
相关产品推荐
相关产品推荐

