【问题标题】:Google App Engine Go 1.11 application can not access Google SpreadsheetsGoogle App Engine Go 1.11 应用程序无法访问 Google 电子表格
【发布时间】:2018-12-14 16:16:53
【问题描述】:

我正在尝试从Google App Engine Go 1.11 Standard Environment 上运行的应用程序通过 API 访问 google 电子表格。 不幸的是,应用程序无法读取this spreadsheet

我在Spreadsheets.Values.Get 通话中遇到下一个错误:

googleapi: Error 403: Request had insufficient authentication scopes., forbidden

示例代码

// Sample app showing issue with GAE -> google spreadsheets
package main

import (
    "context"
    "fmt"
    "log"
    "net/http"
    "os"

    "cloud.google.com/go/compute/metadata"
    "golang.org/x/oauth2/google"
    "google.golang.org/api/sheets/v4"
)

func main() {
    http.HandleFunc("/", indexHandler)

    // [START setting_port]
    port := os.Getenv("PORT")
    if port == "" {
        port = "8080"
        log.Printf("Defaulting to port %s\n", port)
    }

    // let's check app engine instance scopes
    scopes, _ := metadata.Get("instance/service-accounts/default/scopes")
    log.Printf("[DEBUG] metadata scopes: %s.\n", scopes)

    log.Printf("Listening on port %s", port)
    log.Fatal(http.ListenAndServe(fmt.Sprintf(":%s", port), nil))
    // [END setting_port]
}

// indexHandler responds to requests with our greeting.
func indexHandler(w http.ResponseWriter, r *http.Request) {
    ctx := context.Background()
    client, _ := google.DefaultClient(ctx, "https://www.googleapis.com/auth/spreadsheets.readonly")
    srv, err := sheets.New(client)

    // Prints the names and majors of students in a sample spreadsheet:
    // https://docs.google.com/spreadsheets/d/1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms/edit
    spreadsheetId := "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgvE2upms"
    readRange := "Class Data!A2:E"
    resp, err := srv.Spreadsheets.Values.Get(spreadsheetId, readRange).Do()
    if err != nil {
        log.Fatalf("Unable to retrieve data from sheet: %v\n", err)
    }

    if len(resp.Values) == 0 {
        fmt.Fprintf(w, "No data found.\n")
    } else {
        fmt.Fprintf(w, "Name, Major:\n")
        for _, row := range resp.Values {
            // Print columns A and E, which correspond to indices 0 and 4.
            fmt.Fprintf(w, "%s, %s\n", row[0], row[4])
        }
    }

}

重现步骤:

1) 部署应用程序:gcloud app deploy
2)在浏览器中打开(你会得到502):gcloud app browse
3)查看日志:gcloud app logs read

2018-12-11 21:44:56 default[20181211t134352]  "GET / HTTP/1.1" 502
2018-12-11 21:44:57 default[20181211t134352]  2018/12/11 21:44:57 [DEBUG] metadata scopes: https://www.googleapis.com/auth/appengine.apis
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/cloud-platform
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/cloud_debugger
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/devstorage.full_control
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/logging.write
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/monitoring.write
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/trace.append
2018-12-11 21:44:57 default[20181211t134352]  https://www.googleapis.com/auth/userinfo.email
2018-12-11 21:44:57 default[20181211t134352]  .
2018-12-11 21:44:57 default[20181211t134352]  2018/12/11 21:44:57 Listening on port 8081
2018-12-11 21:44:58 default[20181211t134352]  2018/12/11 21:44:58 Unable to retrieve data from sheet: googleapi: Error 403: Request had insufficient authentication scopes., forbidden

有人可以帮助了解如何解决它吗?

示例项目:https://github.com/vistrcm/gae-spreadsheet-issue

【问题讨论】:

    标签: google-app-engine go google-cloud-platform google-sheets-api


    【解决方案1】:

    我之前在 App Engine 与 G Suite 集成中也遇到过这种情况。您需要使用服务帐户密钥。默认值是不够的(我相信是因为它没有私钥,但这可能是错误的)。

    基本上,您需要使用您的代码上传一个密钥并使用它来获取Client(而不是使用默认密钥):

    func getOauthClient(serviceAccountKeyPath string) *http.Client {
        ctx := context.Background()
        data, err := ioutil.ReadFile(serviceAccountKeyPath)
        if err != nil {
            log.Fatal(err)
        }
        creds, err := google.CredentialsFromJSON(ctx, data, "https://www.googleapis.com/auth/spreadsheets.readonly")
        if err != nil {
            log.Fatal(err)
        }
    
        return oauth2.NewClient(ctx, creds.TokenSource)
    }
    

    【讨论】:

    • 谢谢。它可能会起作用。问题是类似的代码在 GAE 中以前版本的 Go 运行时上工作。示例:github.com/vistrcm/gae-spreadsheet-issue/blob/runtime_go/… 试图了解为什么它会因新版本而损坏。
    • 这是第二代运行时。它们不是一对一的相同
    • 嗨@StasVitko,你能确认这个答案是否解决了你的问题吗?
    • 你好@alextru,这个解决方法对我有用。我从应用程序默认凭据切换到通过 JSON 文件显式设置凭据。
    • @StasVitko 这还有必要吗?我相信他们解决了一些问题。你介意检查一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 2017-07-07
    • 2014-01-02
    • 2015-11-15
    相关资源
    最近更新 更多