第三方登录添加gitee

This commit is contained in:
junleea 2025-04-28 13:14:51 +08:00
parent 5aa47993c0
commit 5526a88d94
6 changed files with 181 additions and 45 deletions

View File

@ -61,6 +61,7 @@ func SetUpToolGroup(router *gin.Engine) {
toolGroup.GET("/github_auth", GetGithubAuthUrl)
toolGroup.GET("/get_auth_url", GetThirdPartyAuthUrl)
toolGroup.GET("/github_callback", handleGithubCallback)
toolGroup.GET("/gitee_callback", handleGiteeCallback)
toolGroup.POST("/loginRedirect", LoginRedirect)
//发送邮件
toolGroup.POST("/send_mail", SendMailTool)
@ -666,6 +667,30 @@ func handleGithubCallback(c *gin.Context) {
c.JSON(http.StatusOK, resp)
}
func handleGiteeCallback(c *gin.Context) {
var resp proto.GenerateResp
code := c.Query("code") //code
stateBase64Str := c.Query("state") //state
//解析base64
decodedBytes, err := base64.StdEncoding.DecodeString(stateBase64Str)
if err != nil {
fmt.Println("Decoding error:", err)
} else {
decodedStr := string(decodedBytes)
//json解析
var state proto.ThirdPartyLoginState
err = json.Unmarshal([]byte(decodedStr), &state)
log.Println("handle github callback state:", decodedStr, "\tcode:", code)
if err != nil {
log.Println("json unmarshal error:", err)
}
service.DoGiteeCallBack(&state, code)
}
resp.Code = 0
resp.Message = "success"
c.JSON(http.StatusOK, resp)
}
func GetGithubAuthUrl(c *gin.Context) {
uuid := c.Query("uuid")
hType := c.Query("type") //操作类型add,login
@ -763,6 +788,15 @@ func GetThirdPartyAuthUrl(c *gin.Context) {
params.Add("state", stateBase64Str)
baseUri := proto.GitHuAuthorizeBaseUrl
respUrl = fmt.Sprintf("%s?%s", baseUri, params.Encode())
case "gitee":
params := url.Values{}
params.Add("client_id", proto.Config.GITEE_CLIENT_ID)
//response_type=code
params.Add("response_type", "code")
params.Add("state", stateBase64Str)
//params.Add("redirect_uri", "https://pm.ljsea.top/tool/gitee_callback")
baseUri := proto.GiteeAuthorizeBaseUrl
respUrl = fmt.Sprintf("%s?%s", baseUri, params.Encode())
}
resp.Message = "success"
resp.Code = proto.SuccessCode

View File

@ -87,6 +87,8 @@ type ConfigStruct struct {
KBASE_SERVER []KBaseServer `json:"kbase_server"` // 知识库服务器列表
GITHUB_CLIENT_ID string `json:"github_client_id"` // github client id
GITHUB_CLIENT_SECRET string `json:"github_client_secret"` // github client secret
GITEE_CLIENT_ID string `json:"gitee_client_id"` // gitee client id
GITEE_CLIENT_SECRET string `json:"gitee_client_secret"` // gitee client secret
}
type KBaseServer struct {

View File

@ -191,4 +191,5 @@ const (
const (
GitHuAuthorizeBaseUrl = "https://github.com/login/oauth/authorize"
QQAuthorizeBaseUrl = "https://graph.qq.com/oauth2.0/authorize"
GiteeAuthorizeBaseUrl = "https://gitee.com/oauth/authorize"
)

View File

@ -79,6 +79,10 @@ type ThirdPartyLoginState struct {
UserID int `json:"user_id"` // 用户ID,当为add时需要
}
type OAuthResponse struct {
AccessToken string `json:"access_token"` // access_token
}
// github
type GitHubOAuthResponse struct {
AccessToken string `json:"access_token"`
@ -86,6 +90,22 @@ type GitHubOAuthResponse struct {
TokenType string `json:"token_type"`
}
type GiteeOAuthTokenResponse struct {
AccessToken string `json:"access_token"`
TokenType string `json:"token_type"`
ExpiresIn int `json:"expires_in"`
RefreshToken string `json:"refresh_token"`
Scope string `json:"scope"`
CreatedAt int `json:"created_at"`
}
type OAuthGetTokenRequest struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
Code string `json:"code"`
RedirectURI string `json:"redirect_uri" `
}
type GitHubOAuthRequest struct {
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`

View File

@ -225,6 +225,84 @@ func DoGithubCallBack(state *proto.ThirdPartyLoginState, code string) {
log.Println("get github user info:", userInfo)
var thirdPartyLoginStatus proto.ThirdPartyLoginStatus
thirdPartyLoginStatus.Type = state.Platform
HandleThirdPartyLoginStatus(state, &thirdPartyLoginStatus, &userInfo) //处理第三方登录状态
//更新redis中的第三方登录状态
thirdPartyLoginStatusStr, _ := json.Marshal(thirdPartyLoginStatus)
log.Println("do handle github callback success, third party login status:", string(thirdPartyLoginStatusStr))
worker.SetRedisWithExpire(state.UUID, string(thirdPartyLoginStatusStr), time.Minute*10)
}
// 解析jwt内容
func DecodeJWTToken(tokenStr string) (int, error) {
//解析jwt
// 使用加密secret 解析 JWT 令牌
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return proto.SigningKey, nil
})
if err != nil {
return 0, err
}
// 验证令牌
if !token.Valid {
return 0, fmt.Errorf("invalid token")
}
// 获取用户ID
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return 0, fmt.Errorf("invalid token claims")
}
userID, ok := claims["id"].(float64)
if !ok {
return 0, fmt.Errorf("invalid token claims")
}
return int(userID), nil
}
// 生成token
func GenerateJWTToken(userID int, userName string) (string, error) {
//创建token
claims := jwt.MapClaims{
"id": userID,
"username": userName,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(proto.SigningKey)
if err != nil {
return "", err
}
return tokenString, nil
}
func DoGiteeCallBack(state *proto.ThirdPartyLoginState, code string) {
//获取Access Token
resp, err := worker.GetGiteeAccessTokenByCode(code, "https://pm.ljsea.top/gitee_callback", proto.Config.GITEE_CLIENT_ID, proto.Config.GITEE_CLIENT_SECRET)
if err != nil {
log.Println("get gitee access token error:", err)
return
}
if resp.AccessToken == "" {
log.Println("get gitee access token is empty")
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 github callback success, third party login status:", string(thirdPartyLoginStatusStr))
worker.SetRedisWithExpire(state.UUID, string(thirdPartyLoginStatusStr), time.Minute*10)
}
// 处理第三方登录状态
func HandleThirdPartyLoginStatus(state *proto.ThirdPartyLoginState, thirdPartyLoginStatus *proto.ThirdPartyLoginStatus, userInfo *proto.GitHubUserInfo) {
if state.Type == "login" {
//根据第三方平台查找用户
thirdPartyUserInfoList := dao.FindThirdPartyUserInfoByThirdPartyID(userInfo.UserID)
@ -286,49 +364,4 @@ func DoGithubCallBack(state *proto.ThirdPartyLoginState, code string) {
log.Println("DoGithubCallBack state type error:", state.Type)
thirdPartyLoginStatus.Status = proto.ParameterError //参数错误
}
//更新redis中的第三方登录状态
thirdPartyLoginStatusStr, _ := json.Marshal(thirdPartyLoginStatus)
log.Println("do handle github callback success, third party login status:", string(thirdPartyLoginStatusStr))
worker.SetRedisWithExpire(state.UUID, string(thirdPartyLoginStatusStr), time.Minute*10)
}
// 解析jwt内容
func DecodeJWTToken(tokenStr string) (int, error) {
//解析jwt
// 使用加密secret 解析 JWT 令牌
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return proto.SigningKey, nil
})
if err != nil {
return 0, err
}
// 验证令牌
if !token.Valid {
return 0, fmt.Errorf("invalid token")
}
// 获取用户ID
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return 0, fmt.Errorf("invalid token claims")
}
userID, ok := claims["id"].(float64)
if !ok {
return 0, fmt.Errorf("invalid token claims")
}
return int(userID), nil
}
// 生成token
func GenerateJWTToken(userID int, userName string) (string, error) {
//创建token
claims := jwt.MapClaims{
"id": userID,
"username": userName,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString(proto.SigningKey)
if err != nil {
return "", err
}
return tokenString, nil
}

46
worker/gitee.go Normal file
View File

@ -0,0 +1,46 @@
package worker
import (
"StuAcaWorksAI/proto"
"encoding/json"
)
func GetGiteeAccessTokenByCode(code string, redirectURI string, clientID string, clientSecret string) (proto.GiteeOAuthTokenResponse, error) {
req := proto.OAuthGetTokenRequest{
ClientID: clientID,
ClientSecret: clientSecret,
Code: code,
RedirectURI: redirectURI,
}
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
}