【问题标题】:On App Engine using Go, correct method for using OAuth2在使用 Go 的 App Engine 上,使用 OAuth2 的正确方法
【发布时间】:2015-06-18 21:59:48
【问题描述】:

过去几天我一直在尝试解决这个问题,并且没有高兴地遵循了许多示例和文档,我希望得到一些帮助。

以下给出了 Google 授权页面,但随后返回到 handleOAuth2Callback 页面失败,并出现以下错误:

错误:发布https://accounts.google.com/o/oauth2/token:不是应用程序 引擎上下文

我做错了什么?

import (
    "google.golang.org/appengine"
    "google.golang.org/appengine/log"
    "google.golang.org/cloud"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    // "google.golang.org/api/drive/v2"
    "html/template"
    "net/http"
)

var cached_templates = template.Must(template.ParseGlob("templates/*.html"))

var conf = &oauth2.Config{
    ClientID:     "my client id",
    ClientSecret: "my client secret",
    RedirectURL:  "http://localhost:10080/oauth2callback",
    Scopes: []string{
        "https://www.googleapis.com/auth/drive",
        "https://www.googleapis.com/auth/userinfo.profile",
    },
    Endpoint: google.Endpoint,
}

func init() {
    http.HandleFunc("/", handleRoot)
    http.HandleFunc("/authorize", handleAuthorize)
    http.HandleFunc("/oauth2callback", handleOAuth2Callback)
}

func handleRoot(w http.ResponseWriter, r *http.Request) {
    err := cached_templates.ExecuteTemplate(w, "notAuthenticated.html", nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusNotFound)
    }
}

func handleAuthorize(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    url := conf.AuthCodeURL("")
    http.Redirect(w, r, url, http.StatusFound)
}

func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    hc := &http.Client{}
    ctx := cloud.NewContext(appengine.AppID(c), hc)
    log.Infof(c, "Ctx: %v", ctx)

    code := r.FormValue("code")
    log.Infof(c, "Code: %v", code)

    // Exchange the received code for a token
    tok, err := conf.Exchange(ctx, code)
    // tok, err := conf.Exchange(oauth2.NoContext, code)

    if err != nil {
        log.Errorf(c, "%v", err)
    }
    log.Infof(c, "Token: %v", tok)

    client := conf.Client(oauth2.NoContext, tok)
    log.Infof(c, "Client: %v", client)
}

【问题讨论】:

  • 我无法测试代码,但是,尝试将hc := &http.Client{} 更改为hc := urlfetch.Client(c) 并包含import "appengine/urlfetch"
  • @alvivi 害怕这会出现以下错误:“不能使用 c(类型 context.Context)作为类型“appengine”.Context 在“appengine/urlfetch”的参数中。客户端:context.Context 没有实现“appengine”.Context(缺少调用方法)“
  • 您似乎将google.golang.org/appengine/* 包与AppEngine SDK appengine/* 提供的包混合在一起。仅使用您的 AppEngine SDK 安装提供的包,例如 import "appengine" 而不是 import "google.golang.org/appengine",等等。
  • @alvivi 这是不正确的。应该改用 google.golang.org/appengine 导入。

标签: google-app-engine go oauth-2.0 google-oauth


【解决方案1】:

我当前的解决方案,包括记录登录用户的显示名称和他们 Google 云端硬盘中的所有文件 - 如果您发现任何错误或改进,请发表评论:

import (
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
    "google.golang.org/api/drive/v2"
    "google.golang.org/api/plus/v1"
    "google.golang.org/appengine"
    "google.golang.org/appengine/log"
    "html/template"

    "net/http"
)

var cached_templates = template.Must(template.ParseGlob("templates/*.html"))

var conf = &oauth2.Config{
    ClientID:     "my client id",       // Replace with correct ClientID
    ClientSecret: "my client secret",   // Replace with correct ClientSecret
    RedirectURL:  "http://localhost:10080/oauth2callback",
    Scopes: []string{
        "https://www.googleapis.com/auth/drive",
        "profile",
    },
    Endpoint: google.Endpoint,
}

func init() {
    http.HandleFunc("/", handleRoot)
    http.HandleFunc("/authorize", handleAuthorize)
    http.HandleFunc("/oauth2callback", handleOAuth2Callback)
}

func handleRoot(w http.ResponseWriter, r *http.Request) {
    err := cached_templates.ExecuteTemplate(w, "notAuthenticated.html", nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusNotFound)
    }
}

func handleAuthorize(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    url := conf.AuthCodeURL("")
    http.Redirect(w, r, url, http.StatusFound)
}

func handleOAuth2Callback(w http.ResponseWriter, r *http.Request) {
    c := appengine.NewContext(r)
    code := r.FormValue("code")
    tok, err := conf.Exchange(c, code)
    if err != nil {
        log.Errorf(c, "%v", err)
    }
    client := conf.Client(c, tok)

    // PLUS SERVICE CLIENT
    pc, err := plus.New(client)
    if err != nil {
        log.Errorf(c, "An error occurred creating Plus client: %v", err)
    }
    person, err := pc.People.Get("me").Do()
    if err != nil {
        log.Errorf(c, "Person Error: %v", err)
    }
    log.Infof(c, "Name: %v", person.DisplayName)

    // DRIVE CLIENT
    dc, err := drive.New(client)
    if err != nil {
        log.Errorf(c, "An error occurred creating Drive client: %v", err)
    }
    files, err := dc.Files.List().Do()
    for _, value := range files.Items {
        log.Infof(c, "Files: %v", value.Title)
    }
}

【讨论】:

    猜你喜欢
    • 2013-07-28
    • 1970-01-01
    • 2014-09-23
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 2018-09-04
    • 2023-03-15
    • 1970-01-01
    相关资源
    最近更新 更多