google auth登录

准备

1.调试必须在远程服务端才可以,因为要用到回调系统,或者使用前端的转发工具才可以

2.在https://console.cloud.google.com/apis/dashboard
生成凭据>OAuth 2.0 客户端 ID,

3.设置凭据的回调地址,只能是域名,所以先要将域名解析到远程服务器(除非使用转发工具)

gin实现的简单demo

package main

import (
    "context"
    "encoding/json"
    "log"
    "net/http"
    "github.com/gin-gonic/gin"
    "golang.org/x/oauth2"
    "golang.org/x/oauth2/google"
)

var (
    googleOauthConfig *oauth2.Config
    oauthStateString  = "random"
)

func init() {
    googleOauthConfig = &oauth2.Config{
        RedirectURL:  "http://g.3kj.xyz/auth/google/callback", //回调地址
        ClientID:     "", //客户端id
        ClientSecret: "", //客户端密钥
        Scopes: []string{
            "https://www.googleapis.com/auth/userinfo.email", //获取用户邮箱
        },
        Endpoint: google.Endpoint,
    }
}

func main() {
    router := gin.Default()
    router.LoadHTMLGlob("templates/*")
    router.GET("/", func(c *gin.Context) {
        log.Print("访问首页")
        c.HTML(200, "index.html", nil)
    })
    router.GET("/googlelogin", handleGoogleLogin) //登录路由就是跳转路由
    router.GET("/auth/google/callback", handleGoogleCallback) //回调路由
    router.Run(":5280")
}

//登录函数跳转到
func handleGoogleLogin(c *gin.Context) {
    url := googleOauthConfig.AuthCodeURL(oauthStateString)
    c.Redirect(307, url)
}

//回调函数
func handleGoogleCallback(c *gin.Context) {
    state := c.Request.FormValue("state")
    if state != oauthStateString {
        c.JSON(500, gin.H{"error": "state 不匹配"})
        return
    }

    code := c.Request.FormValue("code")
    token, err := googleOauthConfig.Exchange(context.Background(), code)
    if err != nil {
        c.JSON(500, gin.H{"error": "无法获取 token", "details": err.Error()})
        return
    }

    response, err := http.Get("https://www.googleapis.com/oauth2/v2/userinfo?access_token=" + token.AccessToken)
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": "无法获取用户信息", "details": err.Error()})
        return
    }
    defer response.Body.Close()

    var userInfo struct {
        Email string `json:"email"`
    }
    if err := json.NewDecoder(response.Body).Decode(&userInfo); err != nil {
        c.JSON(500, gin.H{"error": "无法解析用户信息"})
        return
    }
    log.Print("用户信息:",userInfo)
    c.JSON(200, gin.H{"email": userInfo.Email})
}