UserService.go 5.12 KB
Newer Older
Ford committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
package service

import (
	"WorldEpcho/src/config"
	"WorldEpcho/src/config/e"
	"WorldEpcho/src/utils"
	"fmt"
	"github.com/dgrijalva/jwt-go"
	"github.com/gin-contrib/sessions"
	"github.com/gin-gonic/gin"
	"github.com/pkg/errors"
	"net/http"
	"strconv"
	"time"
)

//从session中获取用户id,判断用户是否登录,如果用户已经登录则返回用户id,并返回布尔值
func IsUserLoggedIn2(ctx *gin.Context) (int64, bool) {

	session := sessions.Default(ctx)
	userId := session.Get("WorldUserID")
	if userId == nil {
		// 处理未找到值的情况,返回错误信息
		//ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "Session中未找到用户ID,用户未登录"})
		return 0, false
	}
	// 处理未找到值的情况,返回错误信息
	user_id := utils.Strval(userId)
	//userId作为string类型的值从服务器缓存获取用户id
	_, b := config.WorldLoginCacheCode.Get(user_id)
	uid, err := strconv.ParseInt(user_id, 10, 64)
	if err != nil {
		fmt.Println("转换失败:", err)
		return 0, false
	}
	/*
	   判断用户是否登录
	*/
	if !b {
		//ctx.JSON(http.StatusOK, gin.H{"code": 0, "message": "用户未登录"})
		return 0, false
	}
	return uid, true

}

func IsUserLoggedIn(ctx *gin.Context) (int64, bool) {
	session := sessions.Default(ctx)
	userId := session.Get("WorldUserID")
	if userId != nil {
		user_id := utils.Strval(userId)
		_, b := config.WorldLoginCacheCode.Get(user_id)
		uid, err := strconv.ParseInt(user_id, 10, 64)
		if err == nil && b {
			return uid, true // 如果session验证成功,直接返回
		}
	}

	// 从请求头中获取 JWT token
	tokenString := ctx.GetHeader("Token")
	if tokenString != "" {
		isValid, err := IsValidMiGuToken(tokenString)
		if err == nil && isValid {
			// 解析并验证 JWT token
			token, isValid, err := ParseMIGUToken(tokenString)
			if err == nil && isValid {
				// 提取 Token 中的声明(Claims)
				if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
					if userID, ok := claims["user_id"].(float64); ok {
						return int64(userID), true
					}
				}
			}
		}
	}

	// 如果所有方法都失败,返回未授权的访问错误
	ctx.JSON(http.StatusOK, gin.H{"code": e.UnauthorizedStatus, "data": nil, "message": "未授权的访问或无效的身份验证"})
	return 0, false
}

func MiGuIsUserLoggedIn(ctx *gin.Context) (int64, bool) {
	session := sessions.Default(ctx)
	userId := session.Get("WorldUserID")
	if userId != nil {
		user_id := utils.Strval(userId)
		_, b := config.WorldLoginCacheCode.Get(user_id)
		uid, err := strconv.ParseInt(user_id, 10, 64)
		if err == nil && b {
			return uid, true
		}
	}

	// 从请求头中获取 JWT token
	tokenString := ctx.GetHeader("Token")
	if tokenString == "" {
		ctx.JSON(http.StatusOK, gin.H{"code": e.UnauthorizedStatus, "data": nil, "message": "请求头中无token,或未授权的token访问"})
		return 0, false
	}
	// 解析并验证 JWT 令牌
	isValid, err := IsValidMiGuToken(tokenString)
	if err != nil || !isValid {
		ctx.JSON(http.StatusOK, gin.H{"code": e.InvalidToken, "data": nil, "message": "无效或已过期的令牌"})
		return 0, false
	}

	// 解析并验证 JWT token
	token, isValid, err := ParseMIGUToken(tokenString)
	if err != nil || !isValid {
		fmt.Printf("error parsing token: %v", err)
		return 0, false
	}
	// 提取 Token 中的声明(Claims)
	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		if userID, ok := claims["user_id"].(float64); ok {
			return int64(userID), true
		} else {
			fmt.Printf("user_id claim is missing or type is error")
			return 0, false
		}
	}
	return 0, false
}

// ParseMIGUToken 解析和验证 JWT 令牌,并检查是否过期
func ParseMIGUToken(tokenString string) (*jwt.Token, bool, error) {
	// 使用与生成 Token 相同的密钥
	jwtSecret := []byte(config.Conf.JwtSecret)

	// 解析令牌
	token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
		if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
			return nil, fmt.Errorf("不支持的签名方法: %v", token.Header["alg"])
		}
		return jwtSecret, nil
	})

	if err != nil {
		return nil, false, err // 如果解析过程中发生错误,返回错误信息
	}

	if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
		// 获取令牌的过期时间戳
		if exp, ok := claims["exp"].(float64); ok {
			// 检查令牌是否过期
			now := time.Now().Unix()
			if int64(exp) < now {
				return nil, false, fmt.Errorf("令牌已过期")
			}
			fmt.Println("Token is valid and not expired!")
			fmt.Printf("User ID: %v, Level: %v, Expiry: %v\n", claims["user_id"], claims["level"], time.Unix(int64(exp), 0))
			return token, true, nil // 返回 true 表示令牌有效且未过期
		} else {
			return nil, false, fmt.Errorf("无法获取令牌的过期时间")
		}
	}

	return nil, false, fmt.Errorf("无效的令牌")
}

//校验咪咕的服务商token是否合法
func IsValidMiGuToken(tokenString string) (bool, error) {

	// 解析并验证 JWT token
	_, isValid, err := ParseMIGUToken(tokenString)
	if err != nil || !isValid {
		fmt.Printf("error parsing token: %v", err)
		return false, errors.New("无效的token或解析token出错")
	}
	return true, nil
}