From e3a5d6e49ad44c4a71bf44b1175aa0439f72f3f8 Mon Sep 17 00:00:00 2001 From: junleea <354425203@qq.com> Date: Mon, 28 Apr 2025 21:16:35 +0800 Subject: [PATCH] =?UTF-8?q?google=E7=AC=AC=E4=B8=89=E6=96=B9=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E6=9C=AA=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- handler/tool.go | 10 ++- proto/conf.go | 2 +- proto/status.go | 7 +- proto/tool.go | 9 +++ service/toolService.go | 33 ++++++++ worker/gitee.go | 55 ------------- worker/github.go | 75 ------------------ worker/thirdParty.go | 170 +++++++++++++++++++++++++++++++++++++++++ 8 files changed, 226 insertions(+), 135 deletions(-) delete mode 100644 worker/gitee.go delete mode 100644 worker/github.go create mode 100644 worker/thirdParty.go diff --git a/handler/tool.go b/handler/tool.go index 1a86aff..f43797e 100644 --- a/handler/tool.go +++ b/handler/tool.go @@ -804,6 +804,13 @@ func GetThirdPartyAuthUrl(c *gin.Context) { params.Add("redirect_uri", "https://pm.ljsea.top/tool/gitee_callback") baseUri := proto.GiteeAuthorizeBaseUrl respUrl = fmt.Sprintf("%s?%s", baseUri, params.Encode()) + case "google": + params := url.Values{} + params.Add("client_id", worker.GoogleClientID) + params.Add("response_type", "code") + params.Add("redirect_uri", "https://pm.ljsea.top/tool/third_party_callback") + params.Add("scope", "https://www.googleapis.com/auth/drive.metadata.readonly+https://www.googleapis.com/auth/calendar.readonly") + params.Add("state", stateBase64Str) } resp.Message = "success" resp.Code = proto.SuccessCode @@ -834,8 +841,9 @@ func handleThirdPartyCallback(c *gin.Context) { log.Println("handle github callback state:", decodedStr, "\tcode:", code) if err != nil { log.Println("json unmarshal error:", err) + } else { + service.DoThirdPartyCallBack(&state, code) } - service.DoThirdPartyCallBack(&state, code) } resp.Code = 0 resp.Message = "success" diff --git a/proto/conf.go b/proto/conf.go index 1b8f594..a8b6173 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -9,7 +9,7 @@ import ( var Config ConfigStruct var SigningKey = []byte{} -var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true, "/user/reset": true, "/tool/qq_auth": true, "/tool/qq_callback": true, "/tool/github_auth": true, "/tool/github_callback": true, "/user/oAuth": true, "/user/oAuth_uuid": true, "/tool/loginRedirect": true, "/tool/get_auth_url": true, "/tool/gitee_callback": true, "/tool//third_party_callback": true} // 不需要token验证的url +var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true, "/user/reset": true, "/tool/qq_auth": true, "/tool/qq_callback": true, "/tool/github_auth": true, "/tool/github_callback": true, "/user/oAuth": true, "/user/oAuth_uuid": true, "/tool/loginRedirect": true, "/tool/get_auth_url": true, "/tool/gitee_callback": true, "/tool/third_party_callback": true} // 不需要token验证的url var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3} var File_Type = map[string]int{"im": 1, "avatar": 2, "file": 3, "config": 4} // 文件类型 const ( diff --git a/proto/status.go b/proto/status.go index a227c28..1ce65ad 100644 --- a/proto/status.go +++ b/proto/status.go @@ -189,7 +189,8 @@ const ( // 第三方登录设计url const ( - GitHuAuthorizeBaseUrl = "https://github.com/login/oauth/authorize" - QQAuthorizeBaseUrl = "https://graph.qq.com/oauth2.0/authorize" - GiteeAuthorizeBaseUrl = "https://gitee.com/oauth/authorize" + GitHuAuthorizeBaseUrl = "https://github.com/login/oauth/authorize" + QQAuthorizeBaseUrl = "https://graph.qq.com/oauth2.0/authorize" + GiteeAuthorizeBaseUrl = "https://gitee.com/oauth/authorize" + GoogleAuthorizeBaseUrl = "https://accounts.google.com/o/oauth2/v2/auth" ) diff --git a/proto/tool.go b/proto/tool.go index 17755b4..ed3458d 100644 --- a/proto/tool.go +++ b/proto/tool.go @@ -101,6 +101,15 @@ type GiteeOAuthTokenResponse struct { ErrorDescription string `json:"error_description"` } +type GoogleOAuthResponse struct { +} + +type GoogleOAuthRequest struct { + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + Code string `json:"code"` +} + type OAuthGetTokenRequest struct { ClientID string `json:"client_id"` ClientSecret string `json:"client_secret"` diff --git a/service/toolService.go b/service/toolService.go index e380f0d..56ee49c 100644 --- a/service/toolService.go +++ b/service/toolService.go @@ -412,7 +412,40 @@ func DoThirdPartyCallBack(state *proto.ThirdPartyLoginState, code string) { // TODO case "gogs": // TODO + log.Println("DoThirdPartyCallBack gogs error:", state.Platform) + case "google": + DoGoogleCallBack(state, code) + default: log.Println("DoThirdPartyCallBack platform error:", state.Platform) } } + +func DoGoogleCallBack(state *proto.ThirdPartyLoginState, code string) { + //获取Access Token + resp, err := worker.GetGiteeAccessTokenByCode(code, "https://pm.ljsea.top/tool/gitee_callback", proto.Config.GITEE_CLIENT_ID, proto.Config.GITEE_CLIENT_SECRET) + if err != nil { + log.Println("get google access token error:", err) + return + } + if resp.AccessToken == "" { + log.Println("get gitee access token is empty") + log.Println("get gitee access token error:", resp) + return + } + log.Println("get gitee access token:", resp.AccessToken) + //获取用户信息 + userInfo, err := worker.GetGiteeUserInfo(resp.AccessToken) + if err != nil { + log.Println("get gitee user info error:", err) + return + } + log.Println("get gitee user info:", userInfo) + var thirdPartyLoginStatus proto.ThirdPartyLoginStatus + thirdPartyLoginStatus.Type = state.Platform + HandleThirdPartyLoginStatus(state, &thirdPartyLoginStatus, &userInfo) + //更新redis中的第三方登录状态 + thirdPartyLoginStatusStr, _ := json.Marshal(thirdPartyLoginStatus) + log.Println("do handle gitee callback success, third party login status:", string(thirdPartyLoginStatusStr)) + worker.SetRedisWithExpire(state.UUID, string(thirdPartyLoginStatusStr), time.Minute*10) +} diff --git a/worker/gitee.go b/worker/gitee.go deleted file mode 100644 index e2c6750..0000000 --- a/worker/gitee.go +++ /dev/null @@ -1,55 +0,0 @@ -package worker - -import ( - "StuAcaWorksAI/proto" - "encoding/json" -) - -func GetGiteeAccessTokenByCode(code string, redirectURI string, clientID string, clientSecret string) (proto.GiteeOAuthTokenResponse, error) { - req := proto.GiteeOAuthRequest{ - ClientID: clientID, - ClientSecret: clientSecret, - Code: code, - RedirectURI: redirectURI, - GrantType: "authorization_code", - } - var resp proto.GiteeOAuthTokenResponse - reqBytes, err := json.Marshal(req) - if err != nil { - return resp, err - } - url := "https://gitee.com/oauth/token" - - err2, respBytes := DoPostRequestJSON(url, reqBytes, nil) - if err2 != nil { - return resp, err2 - } - err = json.Unmarshal(respBytes, &resp) - if err != nil { - return resp, err - } - return resp, nil -} - -func GetGiteeUserInfo(accessToken string) (proto.GitHubUserInfo, error) { - url := "https://gitee.com/api/v5/user?access_token=" + accessToken - var resp proto.GitHubUserInfo - err2, respBytes := DoGetRequest(url, nil) - if err2 != nil { - return resp, err2 - } - err := json.Unmarshal(respBytes, &resp) - if err != nil { - return resp, err - } - return resp, nil - -} - -func GetGogsAccessTokenByCode() { - -} - -func GetGogsUserInfo() { - -} diff --git a/worker/github.go b/worker/github.go deleted file mode 100644 index ed60a6b..0000000 --- a/worker/github.go +++ /dev/null @@ -1,75 +0,0 @@ -package worker - -import ( - "StuAcaWorksAI/proto" - "bytes" - "encoding/json" - "errors" - "io" - "net/http" -) - -// 获取access token -func ExchangeCodeForAccessToken(clientID, clientSecret, code, redirectURI string) (proto.GitHubOAuthResponse, error) { - request := proto.GitHubOAuthRequest{ - ClientID: clientID, - ClientSecret: clientSecret, - Code: code, - RedirectURI: redirectURI, - } - - payload, err := json.Marshal(request) - if err != nil { - return proto.GitHubOAuthResponse{}, err - } - - req, err := http.NewRequest("POST", "https://github.com/login/oauth/access_token", bytes.NewBuffer(payload)) - if err != nil { - return proto.GitHubOAuthResponse{}, err - } - - req.Header.Set("Content-Type", "application/json") - req.Header.Set("Accept", "application/json") - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return proto.GitHubOAuthResponse{}, err - } - defer resp.Body.Close() - - body, err := io.ReadAll(resp.Body) - if err != nil { - return proto.GitHubOAuthResponse{}, err - } - - var response proto.GitHubOAuthResponse - err = json.Unmarshal(body, &response) - if err != nil { - return proto.GitHubOAuthResponse{}, err - } - - return response, nil -} - -// 获取用户信息 -func GetGitHubUserInfo(accessToken string) (proto.GitHubUserInfo, error) { - - url := "https://api.github.com/user" - headers := map[string]string{ - "Authorization": "Bearer " + accessToken, - } - err, data := DoGetRequest(url, headers) - var resp proto.GitHubUserInfo - if err != nil { - return resp, err - } - err = json.Unmarshal(data, &resp) - if err != nil { - return resp, err - } - if resp.UserID == 0 { - return resp, errors.New("获取用户信息失败,请检查access_token是否正确") - } - return resp, err -} diff --git a/worker/thirdParty.go b/worker/thirdParty.go new file mode 100644 index 0000000..ae8d78d --- /dev/null +++ b/worker/thirdParty.go @@ -0,0 +1,170 @@ +package worker + +import ( + "StuAcaWorksAI/proto" + "bytes" + "encoding/json" + "errors" + "io" + "net/http" +) + +func GetGiteeAccessTokenByCode(code string, redirectURI string, clientID string, clientSecret string) (proto.GiteeOAuthTokenResponse, error) { + req := proto.GiteeOAuthRequest{ + ClientID: clientID, + ClientSecret: clientSecret, + Code: code, + RedirectURI: redirectURI, + GrantType: "authorization_code", + } + var resp proto.GiteeOAuthTokenResponse + reqBytes, err := json.Marshal(req) + if err != nil { + return resp, err + } + url := "https://gitee.com/oauth/token" + + err2, respBytes := DoPostRequestJSON(url, reqBytes, nil) + if err2 != nil { + return resp, err2 + } + err = json.Unmarshal(respBytes, &resp) + if err != nil { + return resp, err + } + return resp, nil +} + +func GetGiteeUserInfo(accessToken string) (proto.GitHubUserInfo, error) { + url := "https://gitee.com/api/v5/user?access_token=" + accessToken + var resp proto.GitHubUserInfo + err2, respBytes := DoGetRequest(url, nil) + if err2 != nil { + return resp, err2 + } + err := json.Unmarshal(respBytes, &resp) + if err != nil { + return resp, err + } + return resp, nil + +} + +func GetGogsAccessTokenByCode() { + +} + +func GetGogsUserInfo() { + +} + +// 获取access token +func ExchangeCodeForAccessToken(clientID, clientSecret, code, redirectURI string) (proto.GitHubOAuthResponse, error) { + request := proto.GitHubOAuthRequest{ + ClientID: clientID, + ClientSecret: clientSecret, + Code: code, + RedirectURI: redirectURI, + } + + payload, err := json.Marshal(request) + if err != nil { + return proto.GitHubOAuthResponse{}, err + } + + req, err := http.NewRequest("POST", "https://github.com/login/oauth/access_token", bytes.NewBuffer(payload)) + if err != nil { + return proto.GitHubOAuthResponse{}, err + } + + req.Header.Set("Content-Type", "application/json") + req.Header.Set("Accept", "application/json") + + client := &http.Client{} + resp, err := client.Do(req) + if err != nil { + return proto.GitHubOAuthResponse{}, err + } + defer resp.Body.Close() + + body, err := io.ReadAll(resp.Body) + if err != nil { + return proto.GitHubOAuthResponse{}, err + } + + var response proto.GitHubOAuthResponse + err = json.Unmarshal(body, &response) + if err != nil { + return proto.GitHubOAuthResponse{}, err + } + + return response, nil +} + +// 获取用户信息 +func GetGitHubUserInfo(accessToken string) (proto.GitHubUserInfo, error) { + + url := "https://api.github.com/user" + headers := map[string]string{ + "Authorization": "Bearer " + accessToken, + } + err, data := DoGetRequest(url, headers) + var resp proto.GitHubUserInfo + if err != nil { + return resp, err + } + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, err + } + if resp.UserID == 0 { + return resp, errors.New("获取用户信息失败,请检查access_token是否正确") + } + return resp, err +} + +// 谷歌登录授权 +const ( + GoogleClientID = "194888366727-2uvqs43mimk46mmilc04pptrjkqfjn97.apps.googleusercontent.com" + GoogleClientSecret = "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" +) + +func GetGoogleAccessTokenByCode(code string, redirectURI string, clientID string, clientSecret string) (proto.GoogleOAuthResponse, error) { + var resp proto.GoogleOAuthResponse + + url := "https://oauth2.googleapis.com/token" + req := proto.GoogleOAuthRequest{ + ClientID: clientID, + ClientSecret: clientSecret, + Code: code, + } + reqBytes, err := json.Marshal(req) + if err != nil { + return resp, err + } + err2, respBytes := DoPostRequestJSON(url, reqBytes, nil) + if err2 != nil { + return resp, err2 + } + err = json.Unmarshal(respBytes, &resp) + if err != nil { + return resp, err + } + return resp, nil + +} + +func GetGoogleUserInfo(accessToken string) (proto.GitHubUserInfo, error) { + var resp proto.GitHubUserInfo + + url := "https://www.googleapis.com/oauth2/v1/userinfo?access_token=" + accessToken + err, respBytes := DoGetRequest(url, nil) + if err != nil { + return resp, err + } + err = json.Unmarshal(respBytes, &resp) + if err != nil { + return resp, err + } + return resp, nil +}