如何为GOOGLE CLOUD JSON API生成Bearer令牌及GCS上传认证方案咨询
针对你提出的Google Cloud Storage(GCS)对象上传相关问题,我来逐一给你解答:
你当前使用的PHP curl上传代码如下:
<?php $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, "https://www.googleapis.com/upload/storage/v1/b/Mybucket/o?uploadType=media"); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, "yourdata"); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); $headers = array(); $headers[] = "Authorization:Bearer <TOKEN>"; $headers[] = "x-goog-project-id: xxxxxxxxxxx"; $headers[] = "x-goog-user-project: xxxxxxxxxxx"; $headers[] = "Content-Length: 8"; $headers[] = "Content-Type: image/jpeg"; $headers[] = "x-goog-acl: public-read-write"; curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($ch); if (curl_errno($ch)) { echo 'Error:' . curl_error($ch); } curl_close ($ch); ?>
1. 无需Bearer令牌或其他替代认证的上传方法
- 匿名上传(仅限配置公开权限的桶):如果你的存储桶已经设置了
public-read-write的ACL(如你代码中指定的),并且桶的IAM策略允许匿名用户执行上传操作,那么可以直接移除Authorization请求头进行上传。但这种方式风险极高,生产环境绝对不推荐,因为任何知道桶地址的人都能随意上传内容。 - 签名URL上传:这是更安全的无令牌上传方案。你可以在后端使用服务账号密钥生成一个带有过期时间的签名URL,前端或客户端直接使用这个URL就能上传对象,无需携带任何认证令牌。签名URL的权限、有效期都可以精确控制,既避免了令牌管理的麻烦,又保证了安全性。
- 使用官方客户端库(自动处理认证):Google提供了官方的Cloud Storage PHP客户端库,你可以直接使用服务账号JSON密钥初始化客户端,库会自动处理认证流程(包括令牌的生成、缓存和刷新),不需要手动处理Bearer令牌。
2. 编程生成Bearer令牌(curl/PHP方式)
Bearer令牌属于OAuth2.0的访问令牌,针对服务账号场景,通常通过JWT(JSON Web Token)授权流程生成。以下是具体实现方式:
使用curl直接生成
你可以通过向Google的令牌端点发送请求,用服务账号JSON密钥生成JWT并交换访问令牌:
# 假设你的服务账号密钥文件名为service-account.json curl -X POST "https://oauth2.googleapis.com/token" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer" \ -d "assertion=$(python3 -c ' import jwt import time import json with open("service-account.json") as f: data = json.load(f) payload = { "iss": data["client_email"], "scope": "https://www.googleapis.com/auth/devstorage.read_write", "aud": "https://oauth2.googleapis.com/token", "exp": int(time.time()) + 3600, "iat": int(time.time()) } print(jwt.encode(payload, data["private_key"], algorithm="RS256")) ')"
执行后会返回包含access_token的JSON响应,这个值就是你需要的Bearer令牌,有效期默认1小时。
使用PHP生成
你可以借助firebase/php-jwt库生成JWT,再通过HTTP请求交换令牌:
首先安装依赖:
composer require firebase/php-jwt guzzlehttp/guzzle
然后编写代码:
<?php require 'vendor/autoload.php'; use Firebase\JWT\JWT; use GuzzleHttp\Client; // 加载服务账号密钥文件 $serviceAccount = json_decode(file_get_contents('service-account.json'), true); $now = time(); // 构造JWT payload $payload = [ 'iss' => $serviceAccount['client_email'], // 服务账号邮箱 'scope' => 'https://www.googleapis.com/auth/devstorage.read_write', // 所需权限 'aud' => 'https://oauth2.googleapis.com/token', // 令牌端点地址 'exp' => $now + 3600, // 令牌有效期1小时 'iat' => $now // 令牌签发时间 ]; // 生成JWT $jwt = JWT::encode($payload, $serviceAccount['private_key'], 'RS256'); // 发送请求获取access token $client = new Client(); $response = $client->post('https://oauth2.googleapis.com/token', [ 'form_params' => [ 'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer', 'assertion' => $jwt ] ]); $tokenData = json_decode($response->getBody(), true); $accessToken = $tokenData['access_token']; // 现在可以将$accessToken用于你的上传请求 echo "Bearer Token: " . $accessToken; ?>
更简便的方式:使用官方PHP客户端库
如果你直接使用Google官方的Cloud Storage PHP客户端库,它会自动处理令牌的生成和刷新,无需手动实现上述流程:
<?php require 'vendor/autoload.php'; use Google\Cloud\Storage\StorageClient; // 使用服务账号密钥初始化客户端 $storage = new StorageClient([ 'keyFilePath' => 'service-account.json' ]); // 获取目标存储桶 $bucket = $storage->bucket('Mybucket'); // 上传对象(这里以本地文件为例) $bucket->upload(file_get_contents('your-file.jpg'), [ 'contentType' => 'image/jpeg', 'acl' => 'public-read-write' ]); ?>
内容的提问来源于stack exchange,提问作者Eldhose Elias




