Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用GoogleAPI交换OAUTH令牌(Go)_Oauth_Go_Google Oauth - Fatal编程技术网

如何使用GoogleAPI交换OAUTH令牌(Go)

如何使用GoogleAPI交换OAUTH令牌(Go),oauth,go,google-oauth,Oauth,Go,Google Oauth,这里是我到目前为止得到的返回“400错误”的结果。我做错什么了吗?我不明白为什么不工作,因为请求非常简单 package main import ( "code.google.com/p/goauth2/oauth" "fmt" "log" ) func main() { cachefile := "cache.json" code := "4/xxxxx.8uFT5Z0slpMbJvIeHux6iLY_9k7ajw" //the code recei

这里是我到目前为止得到的返回“400错误”的结果。我做错什么了吗?我不明白为什么不工作,因为请求非常简单

package main

import (
    "code.google.com/p/goauth2/oauth"
    "fmt"
    "log"
)

func main() {
    cachefile := "cache.json"
    code := "4/xxxxx.8uFT5Z0slpMbJvIeHux6iLY_9k7ajw" //the code received from the URL redirect
    // Set up a configuration.
    config := &oauth.Config{
        ClientId:     "xx.apps.googleusercontent.com",
        ClientSecret: "cWP3HudD3XmaP33j8",
        RedirectURL:  "https://crm.com/sender/gmail/auth/callBack",
        Scope:        "https://www.googleapis.com/auth/gmail.compose",
        AuthURL:      "https://accounts.google.com/o/oauth2/auth",
        TokenURL:     "https://accounts.google.com/o/oauth2/token",
        AccessType:   "offline",
        TokenCache:   oauth.CacheFile(cachefile),
    }

    // Set up a Transport using the config.
    transport := &oauth.Transport{Config: config}
    token, err := config.TokenCache.Token()
    if err != nil {
        token, err = transport.Exchange(code)
        if err != nil {
            log.Fatal("Exchange:", err)
        }
    }
    // (The Exchange method will automatically cache the token.)

    transport.Token = token
    fmt.Println(token)
}
结果

Exchange:OAuthError: updateToken: Unexpected HTTP status 400 Bad Request

我建议使用“一次性代码流”,如下所述:

要利用Google+登录的所有好处,您必须使用混合服务器端流程,其中用户使用JavaScript API客户端在客户端授权您的应用程序,您向服务器发送一个特殊的一次性授权代码。您的服务器交换此一次性使用代码,以从Google获取自己的访问权限并刷新令牌,以便服务器能够进行自己的API调用,这可以在用户脱机时完成。与纯服务器端流和向服务器发送访问令牌相比,此一次性代码流具有安全优势

因为代码只需使用一次,就不太可能破坏用户帐户

客户端代码非常简单,请遵循下面的示例

对于服务器端,我建议使用包而不是
goauth2

$ go get code.google.com/p/google-api-go-client/plus/v1
$ go get github.com/golang/oauth2
$ go get google.golang.org/appengine
出于某种原因,
oauth2
包还需要
appengine

可以使用以下函数将一次性代码交换为可重用令牌:

最后,您在步骤3中创建的代码可以将一次性代码提交给在
/oauth2
上侦听的处理程序:

func oauth2Handler(w http.ResponseWriter, r *http.Request) {
    // TODO Check request has...
    // - Method: POST
    // - Content-Type: application/octet-stream; charset=utf-8
    // - CSRF Token http://goo.gl/mNCjJm

    body, err := ioutil.ReadAll(r.Body)
    defer r.Body.Close()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    code := string(body[:])
    token, transport, err := exchangeCode(code)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // From here you can use the transport
    client := http.Client{Transport: transport}
    service, err := plus.New(&client)
    if err != nil {
        return nil, err
    }

    // https://www.googleapis.com/plus/v1/people/me
    person, err := service.People.Get("me").Do()
    // ...
}

func main() {
    http.HandleFunc("/oauth2", oauth2Handler)
    log.Fatal(http.ListenAndServe(":8000", nil))
}

缺少一些错误处理,但您知道了。

您的程序中有一个硬编码的访问代码。这些是一次性使用的,那么您是否已经使用过代币?您是对的。。。我以为“代码”实际上是刷新令牌。对。代码是在用户对服务进行身份验证时通过用户的web浏览器传递到重定向URL的代码。您使用该一次性代码创建多用途访问令牌。google.NewConfig中的重定向URL值是多少???答案来自2014年。。。我建议您检查文档,它可能已经更改了好几次
func oauth2Handler(w http.ResponseWriter, r *http.Request) {
    // TODO Check request has...
    // - Method: POST
    // - Content-Type: application/octet-stream; charset=utf-8
    // - CSRF Token http://goo.gl/mNCjJm

    body, err := ioutil.ReadAll(r.Body)
    defer r.Body.Close()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    code := string(body[:])
    token, transport, err := exchangeCode(code)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    // From here you can use the transport
    client := http.Client{Transport: transport}
    service, err := plus.New(&client)
    if err != nil {
        return nil, err
    }

    // https://www.googleapis.com/plus/v1/people/me
    person, err := service.People.Get("me").Do()
    // ...
}

func main() {
    http.HandleFunc("/oauth2", oauth2Handler)
    log.Fatal(http.ListenAndServe(":8000", nil))
}