up
This commit is contained in:
103
getway/main.go
103
getway/main.go
@@ -11,6 +11,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-contrib/cors"
|
||||
"github.com/gin-contrib/sessions"
|
||||
"github.com/gin-contrib/sessions/cookie"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/golang-jwt/jwt"
|
||||
"github.com/google/go-github/v50/github"
|
||||
@@ -42,6 +44,9 @@ func main() {
|
||||
|
||||
router := gin.Default()
|
||||
|
||||
store := cookie.NewStore([]byte("secret"))
|
||||
router.Use(sessions.Sessions("my-session", store))
|
||||
|
||||
router.Use(cors.New(cors.Config{
|
||||
AllowOrigins: []string{"*"},
|
||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS", "HEAD"},
|
||||
@@ -56,15 +61,14 @@ func main() {
|
||||
}
|
||||
|
||||
func githubLoginHandler(c *gin.Context) {
|
||||
// state := generateState()
|
||||
// code := generateCode()
|
||||
state := generateState()
|
||||
|
||||
// err := storeStateToDB(state, code)
|
||||
// if err != nil {
|
||||
// log.Println("Error storing state to DB:", err)
|
||||
// c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"message": "Internal server error"})
|
||||
// return
|
||||
// }
|
||||
session := sessions.Default(c)
|
||||
session.Set("state", state)
|
||||
if err := session.Save(); err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
url := oauthConf.AuthCodeURL("state")
|
||||
log.Println(url)
|
||||
@@ -72,30 +76,27 @@ func githubLoginHandler(c *gin.Context) {
|
||||
}
|
||||
|
||||
func githubCallbackHandler(c *gin.Context) {
|
||||
state := c.Query("state")
|
||||
code := c.Query("code")
|
||||
log.Println(state, code)
|
||||
|
||||
// if !verifyState(state, code) {
|
||||
// c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"message": "Invalid state"})
|
||||
// return
|
||||
// }
|
||||
code, state := c.Query("code"), c.Query("state")
|
||||
session := sessions.Default(c)
|
||||
savedState := session.Get("state")
|
||||
if savedState == nil || savedState.(string) != state {
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": "Invalid state parameter."})
|
||||
return
|
||||
}
|
||||
|
||||
// 使用 code 换取 token
|
||||
token, err := oauthConf.Exchange(context.Background(), code)
|
||||
if err != nil {
|
||||
// c.String(http.StatusBadRequest, "授权失败: %s", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": fmt.Errorf("授权失败: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
log.Println("token:", token)
|
||||
|
||||
// 使用 token 获取 GitHub 用户信息
|
||||
// client := github.NewClient(oauthConf.Client(context.Background(), token))
|
||||
client := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(token)))
|
||||
client := github.NewClient(oauthConf.Client(context.Background(), token))
|
||||
// client := github.NewClient(oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(token)))
|
||||
user, _, err := client.Users.Get(c.Request.Context(), "")
|
||||
if err != nil {
|
||||
// c.String(http.StatusInternalServerError, "获取用户信息失败: %s", err.Error())
|
||||
c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": fmt.Errorf("获取用户信息失败: %s", err.Error())})
|
||||
return
|
||||
}
|
||||
@@ -111,6 +112,7 @@ func githubCallbackHandler(c *gin.Context) {
|
||||
log.Println(user.GetEmail(), user.GetName(), user.GetID(), user.GetAvatarURL())
|
||||
// 处理用户信息
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"id": user.ID,
|
||||
"login": user.Login,
|
||||
"name": user.Name,
|
||||
"email": user.Email,
|
||||
@@ -203,19 +205,21 @@ func storeUserToDB(user *github.User) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func generateJWTToken(userID int64) (string, error) {
|
||||
// Generate a signed JWT containing the user ID as a claim.
|
||||
func generateJWT(userID int64) (string, error) {
|
||||
token := jwt.New(jwt.SigningMethodHS256)
|
||||
claims := jwt.MapClaims{
|
||||
"sub": userID,
|
||||
"exp": time.Now().Add(24 * time.Hour).Unix(),
|
||||
}
|
||||
token.Claims = claims
|
||||
|
||||
claims := token.Claims.(jwt.MapClaims)
|
||||
claims["user"] = userID
|
||||
claims["exp"] = time.Now().Add(time.Hour * 24).Unix()
|
||||
|
||||
jwtToken, err := token.SignedString(jwtSecret)
|
||||
signedToken, err := token.SignedString(jwtSecret)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return jwtToken, nil
|
||||
return signedToken, nil
|
||||
}
|
||||
|
||||
func verifyJWTToken(tokenString string) {
|
||||
@@ -242,3 +246,48 @@ func verifyJWTToken(tokenString string) {
|
||||
fmt.Println("Invalid token.")
|
||||
}
|
||||
}
|
||||
|
||||
// Middleware to require authentication via JWT.
|
||||
func requireAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
tokenString := c.GetHeader("Authorization")
|
||||
if tokenString == "" {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Missing Authorization header."})
|
||||
return
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
|
||||
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
|
||||
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
|
||||
}
|
||||
return jwtSecret, nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if err == jwt.ErrSignatureInvalid {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token signature."})
|
||||
return
|
||||
}
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token."})
|
||||
return
|
||||
}
|
||||
|
||||
claims, ok := token.Claims.(jwt.MapClaims)
|
||||
if !ok || !token.Valid {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid token claims."})
|
||||
return
|
||||
}
|
||||
|
||||
userID, ok := claims["sub"].(float64)
|
||||
if !ok {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{"error": "Invalid subject claim type."})
|
||||
return
|
||||
}
|
||||
|
||||
// Use the userID to look up the user in your database or perform other authorization logic.
|
||||
// ...
|
||||
// If authorized, set the user ID on the Gin context for use by downstream handlers.
|
||||
c.Set("userID", int64(userID))
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user