我创建了Google电子表格,并授予了所有人编辑权限(即使没有登录也可以编辑)。
这是链接。我想通过Google电子表格API更新此表格。但是我一直得到错误提示。我的要求是通过API更新该表格,而无需访问凭据。
我创建了Google电子表格,并授予了所有人编辑权限(即使没有登录也可以编辑)。
这是链接。我想通过Google电子表格API更新此表格。但是我一直得到错误提示。我的要求是通过API更新该表格,而无需访问凭据。
服务账户密钥
而不需要OAuth
或API密钥
来写入电子表格。提供新的私有密钥
JSON
。服务账户密钥
包括一个client_email
。
client_email
对此文档进行写入访问。使用以下代码进行身份验证:
let jwtClient = new google.auth.JWT(client_email, null, private_key, [
"https://www.googleapis.com/auth/spreadsheets",
]);
//authenticate request
jwtClient.authorize(function(err, tokens) {
// 在这一点上,身份验证已完成,您现在可以使用`jwtClient`读取或写入电子表格。
});
client_email
和private_key
是服务账户密钥
的一部分。这里可以找到更详细的描述:http://isd-soft.com/tech_blog/accessing-google-apis-using-service-account-node-js/同时,所有功劳归功于该页面。
您需要获得授权才能进行此类请求
您的应用程序发送到Google Sheets API的每个请求都需要将您的应用程序标识给Google。有两种方法可以标识您的应用程序:使用OAuth 2.0令牌(也授权该请求)和/或使用应用程序的API密钥。以下是如何确定使用哪些选项:
如果请求需要授权(例如请求某个人的私人数据),则应用程序必须在请求中提供OAuth 2.0令牌。应用程序还可以提供API密钥,但不一定要提供。如果请求不需要授权(例如请求公共数据),则应用程序必须提供API密钥或OAuth 2.0令牌,或两者都提供——无论哪种选项对您来说最方便。
就是这样。无法绕过授权。
最后深入挖掘,找到了答案。任何类型的写作,即使是对公开可编辑的表格,也需要进行OAuth流程:
private static String getSignedJWT() throws IOException {
InputStream in = YourClass.class.getResourceAsStream("/downloaded-service-account-creds.json");
if (in == null) {
throw new FileNotFoundException("Resource not found");
}
ServiceAccountCredentials serviceAccountCredentials = ServiceAccountCredentials.fromStream(in);
GoogleCredentials googleCredentials = serviceAccountCredentials
.createScoped(Collections.singletonList(SheetsScopes.SPREADSHEETS));
PrivateKey privateKey = serviceAccountCredentials.getPrivateKey();
String privateKeyId = serviceAccountCredentials.getPrivateKeyId();
long now = System.currentTimeMillis();
Algorithm algorithm = Algorithm.RSA256(null, (RSAPrivateKey)privateKey);
String signedJwt = JWT.create()
.withKeyId(privateKeyId)
.withIssuer(serviceAccountCredentials.getClientEmail())
.withSubject(serviceAccountCredentials.getClientEmail())
.withAudience("https://sheets.googleapis.com/")
.withIssuedAt(new Date(now))
.withExpiresAt(new Date(now + 3600 * 1000L))
.sign(algorithm);
return signedJwt;
}
所需依赖项:com.auth0:java-jwt和com.google.auth:google-auth-library-oauth2-http。
以下是使用上述生成的JWT字符串的curl命令:
curl --location --request POST 'https://sheets.googleapis.com/v4/spreadsheets/YOUR_SHEET_ID:batchUpdate?key=ANY_PERSONAL_API_KEY' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_STRING' \
--data-raw '{
"requests": [
{
"addSheet": {
"properties": {
"title": "newPred",
"sheetId": 0
}
}
},
{
"pasteData": {
"coordinate": {
"columnIndex": 0,
"rowIndex": 0,
"sheetId": 0
},
"delimiter": "\t",
"data": "col1\tcol2\nPeter\t25",
"type": "PASTE_NORMAL"
}
}
]
}'
虽然不完全符合要求,但这是一个对我有效的解决方案,使用google-api-nodejs-client实现:
const { google } = require('googleapis');
const sheets = google.sheets('v4');
const spreadsheetId = '.........';
(async () => {
const auth = new google.auth.GoogleAuth({
keyFile: './my_service_account_privatekey.json',
scopes: ['https://www.googleapis.com/auth/spreadsheets'],
});
// get
try {
const getResult = await sheets.spreadsheets.values.get({
auth,
spreadsheetId,
range: 'Sheet1!B2:C4'
})
console.log('Got values:', getResult.data.values)
} catch (error) {
console.error('Get error:', error)
}
})()
文档:https://github.com/googleapis/google-api-nodejs-client#using-the-keyfile-property