dongwujie7477 2018-12-11 22:03
浏览 83
已采纳

Google App Engine Go 1.11应用程序无法访问Google Spreadsheets

I'm trying to access google spreadsheet via API from the application running on Google App Engine Go 1.11 Standard Environment. Unfortunately, the application cannot read this spreadsheet.

I'm getting next error on Spreadsheets.Values.Get call:

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

sample code

// 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
", port)
    }

    // let's check app engine instance scopes
    scopes, _ := metadata.Get("instance/service-accounts/default/scopes")
    log.Printf("[DEBUG] metadata scopes: %s.
", 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
", err)
    }

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

}

steps to reproduce:

1) deploy app: gcloud app deploy
2) open in a browser (you will get 502): gcloud app browse
3) check logs: 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

Could someone please help to understand how to fix it?

Sample project: https://github.com/vistrcm/gae-spreadsheet-issue

  • 写回答

1条回答 默认 最新

  • dongzhuifeng1843 2018-12-11 22:19
    关注

    I've ran into this before as well with App Engine to G Suite integrations. You need to use a service account key. The default one does not suffice (I believe because it does not have a private key, but that might be wrong).

    Essentially you will need to upload a key with your code and use that to get a Client (instead of using the default one):

    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)
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 在若依框架下实现人脸识别
  • ¥15 网络科学导论,网络控制
  • ¥100 安卓tv程序连接SQLSERVER2008问题
  • ¥15 利用Sentinel-2和Landsat8做一个水库的长时序NDVI的对比,为什么Snetinel-2计算的结果最小值特别小,而Lansat8就很平均
  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同