不需要身份验证令牌即可访问Google电子表格API

28

我创建了Google电子表格,并授予了所有人编辑权限(即使没有登录也可以编辑)。

这是链接。我想通过Google电子表格API更新此表格。但是我一直得到错误提示。我的要求是通过API更新该表格,而无需访问凭据。

输入图像描述


1
你找到解决方案了吗?似乎即使开启“任何人都可以编辑模式”,我们也只能读取数据,而不能更改或添加一些内容。 - Allan Raquin
5个回答

19
可以使用服务账户密钥而不需要OAuthAPI密钥来写入电子表格。
以下是在我的Node.js环境中所做的步骤:
  1. https://console.cloud.google.com/apis/credentials获取一个服务账户密钥(您还可以在此限制此密钥的权限)。
    1. 创建时,请确保单击提供新的私有密钥
    2. 当询问如何下载密钥时,请选择JSON
  2. 您刚生成的服务账户密钥包括一个client_email
    1. 转到您的谷歌电子表格,并允许此client_email对此文档进行写入访问。
  3. 使用以下代码进行身份验证:

    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_emailprivate_key服务账户密钥的一部分。

这里可以找到更详细的描述:http://isd-soft.com/tech_blog/accessing-google-apis-using-service-account-node-js/同时,所有功劳归功于该页面。


NVM(对于未来的观众)只是没有调用require("googleapis").google(https://github.com/googleapis/google-api-nodejs-client#getting-started) - Yaakov5777
我们如何通过Java实现这个目标? - Dhruv Singhal

4

您需要获得授权才能进行此类请求

您的应用程序发送到Google Sheets API的每个请求都需要将您的应用程序标识给Google。有两种方法可以标识您的应用程序:使用OAuth 2.0令牌(也授权该请求)和/或使用应用程序的API密钥。以下是如何确定使用哪些选项:

如果请求需要授权(例如请求某个人的私人数据),则应用程序必须在请求中提供OAuth 2.0令牌。应用程序还可以提供API密钥,但不一定要提供。如果请求不需要授权(例如请求公共数据),则应用程序必须提供API密钥或OAuth 2.0令牌,或两者都提供——无论哪种选项对您来说最方便。

就是这样。无法绕过授权。


我已经创建了 API 密钥,并将其添加到 Postman 的头部。 密钥:Authorization 值:key=<api_key>,但仍然无法正常工作。 - Nageswaran
@Nageswaran 你必须将它作为查询字符串传递,而不是头部。请参阅 https://developers.google.com/sheets/api/guides/authorizing#APIKey - mtricht
相同的密钥可以用于GET请求,但不能用于PUT请求 :/。我有什么遗漏吗? - Divyansh Singh
1
这里有同样的问题。上述限制仅涵盖对数据的读取,而不涉及对表格进行写入,即使该表格已经向公众开放了完全编辑权限。希望他们能够更清楚地阐明这一点。在完全开放的形式中进行写入是有很好的使用案例的。 - Andrew

2

1
Jürgen Brandstetter的回答是完全正确的。使用Postman,我成功地进行了操作,而无需使用OAuth令牌(我需要我的个人API密钥和服务帐户)- 我写入了一个新的工作表(实际上我进行了批量更新操作,有两个步骤,首先创建一个新的工作表,然后在其上粘贴数据)。我按照这里的说明创建了一个服务帐户,下载了凭据JSON并用它创建和签署JWT字符串,稍后将其用作Bearer。
以下是获取JWT字符串的Java代码:
    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"
            }
        }
    ]
}'

0

虽然不完全符合要求,但这是一个对我有效的解决方案,使用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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接