package router import ( "bytes" "fmt" "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" "io/ioutil" "net/http" "time" ) // 伪装数据库,存储授权码和访问令牌 var db = map[string]string{} type UserInfo struct { Sub string `json:"sub"` Name string `json:"name"` GivenName string `json:"given_name"` FamilyName string `json:"family_name"` PreferredUsername string `json:"preferred_username"` Email string `json:"email"` EmailVerified bool `json:"email_verified"` Picture string `json:"picture"` // ...其他字段... } func GiteaRoute(router *gin.RouterGroup) { r := router.Group("sso") // OpenID发现文档端点 r.GET("/.well-known/openid-configuration", func(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "issuer": "https://common.szjixun.cn", "authorization_endpoint": "https://common.szjixun.cn/api/sso/auth", "token_endpoint": "https://common.szjixun.cn/api/sso/token", "userinfo_endpoint": "https://common.szjixun.cn/api/sso/userinfo", "jwks_uri": "https://common.szjixun.cn/api/sso/.well-known/jwks.json", // 你可以添加其他必要的OIDC配置项 }) }) // 授权端点 r.GET("/auth", func(c *gin.Context) { // 验证用户登录,并重定向到回调地址,带上授权码code // 这里需要开发者实现用户认证逻辑,并生成授权码 authCode := "your_generated_auth_code" db[authCode] = "asdkfljoqeruowerql" c.Redirect(http.StatusFound, c.Query("redirect_uri")+"?code="+authCode+"&state="+c.Query("state")) }) // 令牌端点 r.POST("/token", func(c *gin.Context) { fmt.Println("令牌断电") fmt.Println(c.PostForm("client_id")) fmt.Println(c.PostForm("client_secret")) // 根据授权码生成访问令牌 // 这里需要验证授权码是否有效,并生成访问令牌 //authCode := c.PostForm("code") bodyBytes, err := ioutil.ReadAll(c.Request.Body) if err != nil { c.String(500, "Reading body error: %s", err.Error()) return } // Body内容读取后,需要把它再放回去 c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes)) // 打印Body内容 bodyString := string(bodyBytes) fmt.Println("Body:", bodyString) token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "iss": "https://common.szjixun.cn", // 你的管理系统 URL "sub": "248289761001", "aud": "GiteaClientID", // Gitea OAuth 应用的 client_id "exp": time.Now().Add(time.Hour * 72).Unix(), "iat": time.Now().Unix(), }) tokenString, err := token.SignedString([]byte("YourSecretKey")) // 使用你的密钥对其进行签名 if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "Could not generate token"}) return } //if accessToken, ok := db[authCode]; ok { c.JSON(http.StatusOK, gin.H{ "access_token": "asdkfljoqeruowerql", "token_type": "bearer", "expires_in": 7200, // 建议加上令牌过期时间 "id_token": tokenString, // ID令牌通常包含用户信息的JWT }) return //} c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_authorization_code"}) }) // 用户信息端点 r.GET("/userinfo", func(c *gin.Context) { fmt.Println("用户信息") // 校验访问令牌,并返回用户信息 // 这里需要验证访问令牌是否有效 accessToken := c.GetHeader("Authorization") fmt.Println(accessToken) fmt.Println(c.Request.URL.Query()) //if user, ok := db[accessToken]; ok { userInfo := UserInfo{ Sub: "248289761001", Name: "Jane Doe", GivenName: "Jane", FamilyName: "Doe", PreferredUsername: "j.doe", Email: "janedoe@example.com", EmailVerified: true, Picture: "http://example.com/janedoe/me.jpg", } c.JSON(http.StatusOK, userInfo) return //} c.JSON(http.StatusBadRequest, gin.H{"error": "invalid_token"}) }) }