我在使用Google OAuth2进行身份验证时遇到了问题。
我从谷歌开发者控制台获得了客户端ID和秘密,我想出了这段代码:
package main
import (
"fmt"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"io/ioutil"
"net/http"
"os"
)
const htmlIndex = `<html><body>
<a href="/GoogleLogin">Log in with Google</a>
</body></html>
`
func init() {
// Setup Google's example test keys
os.Setenv("CLIENT_ID", "somrestring-otherstring.apps.googleusercontent.com")
os.Setenv("SECRET_KEY", "alongcharachterjumble")
}
var (
googleOauthConfig = &oauth2.Config{
RedirectURL: "http://127.0.0.1:8080/auth", //defined in Google console
ClientID: os.Getenv("CLIENT_ID"),
ClientSecret: os.Getenv("SECRET_KEY"),
Scopes: []string{"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/userinfo.email"},
Endpoint: google.Endpoint,
}
// Some random string, random for each request
oauthStateString = "random"
)
func main() {
http.HandleFunc("/", handleMain)
http.HandleFunc("/GoogleLogin", handleGoogleLogin)
http.HandleFunc("/GoogleCallback", handleGoogleCallback)
fmt.Println(http.ListenAndServe(":8080", nil))
}
func handleMain(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, htmlIndex)
fmt.Println("another request made")
}
func handleGoogleLogin(w http.ResponseWriter, r *http.Request) {
url := googleOauthConfig.AuthCodeURL(oauthStateString)
http.Redirect(w, r, url, http.StatusTemporaryRedirect)
}
func handleGoogleCallback(w http.ResponseWriter, r *http.Request) {
state := r.FormValue("state")
if state != oauthStateString {
fmt.Printf("invalid oauth state, expected '%s', got '%s'\n", oauthStateString, state)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
code := r.FormValue("code")
token, err := googleOauthConfig.Exchange(oauth2.NoContext, code)
if err != nil {
fmt.Println("Code exchange failed with '%s'\n", err)
http.Redirect(w, r, "/", http.StatusTemporaryRedirect)
return
}
response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken)
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
fmt.Fprintf(w, "Content: %s\n", contents)
}
但是我从谷歌那里得到了这个错误:
- 这是一个错误。
醇>错误:invalid_request
缺少必需参数:client_id
了解详情
请求详细信息client_id = redirect_uri = http://127.0.0.1:8080/auth RESPONSE_TYPE =代码 范围= https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email州=随机
这里有什么问题?我该如何解决?
答案 0 :(得分:1)
错误消息表明ClientID
未初始化。
这看起来与代码一致,因为var
声明在init
函数之前执行。
因此,当您var
请求os.Getenv("CLIENT_ID")
时,该值为空,因为init
尚未执行。
来自文档:
通过为其所有包级变量分配初始值,然后按照它们在源中出现的顺序(可能在多个文件中)调用所有init函数来初始化没有导入的包,如提供给编译器
https://golang.org/ref/spec#Package_initialization
要解决此问题,请将字符串直接放在var
初始化中,或者在设置值后从init
触发初始化。
像:
var (
googleOauthConfig *oauth2.Config
)
func init() {
// init ENV
// initialize the variable using ENV values
googleOauthConfig = &oauth2.Config{ ... }
}
或者,您可以在执行实际Go程序之前在OS级别设置这些ENV
值。