package jwthelper import ( "go-admin/common/const/rediskey" "go-admin/common/helper" "go-admin/pkg/utility" "github.com/golang-jwt/jwt/v5" "go.uber.org/zap" "fmt" "strings" "time" log "github.com/go-admin-team/go-admin-core/logger" ) // LoginUserJwt 用户登入信息 type LoginUserJwt struct { UserID int NickName string Phone string Email string OsType int } // LoginClaims 自定义声明结构体并内嵌jwt.StandardClaims // jwt包自带的jwt.StandardClaims只包含了官方字段 // 我们这里需要额外记录一个nickname字段,所以要自定义结构体 // 如果想要保存更多信息,都可以添加到这个结构体中 type LoginClaims struct { UserID int `json:"userid"` NickName string `json:"nickname"` Phone string `json:"phone"` Email string `json:"email"` jwt.RegisteredClaims } // JwtSigningKey Jwt signing key var JwtSigningKey = []byte("tokexapp.com") var LoginTokenValidTime = 48 * time.Hour // 登录验证token有效期 var LoginAdminTokenValidTime = 24 * time.Hour var TokenNotValid = -1 // Token无效 var TokenExpire = -2 // Token过期 var TokenSuccess = 1 // Token正常 // CreateJwtToken 创建用户jwt token func CreateJwtToken(userJwt LoginUserJwt, minute int) (string, string) { // 创建一个我们自己的声明 expire := time.Now().Add(time.Minute * time.Duration(minute)) //.Unix() claims := LoginClaims{ UserID: userJwt.UserID, Phone: userJwt.Phone, NickName: userJwt.NickName, Email: userJwt.Email, RegisteredClaims: jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(expire), Issuer: "Tokex", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) tokenStr, err := token.SignedString(JwtSigningKey) if err != nil { log.Error("获取jwt token失败:", zap.Error(err)) return "", "" } return tokenStr, fmt.Sprintf("%v", expire.Unix()) } // MidValidToken 检验token是否有效,返回token解密后的string func MidValidToken(tokenStr string, source int) (int, string) { // 解析token token, err := jwt.ParseWithClaims(tokenStr, &LoginClaims{}, func(token *jwt.Token) (i interface{}, err error) { return JwtSigningKey, nil }) if err != nil { if strings.Contains(err.Error(), "token is expired") { return TokenExpire, "" } // loghelper.Error("MidValidToken解析token失败", zap.Error(err)) return TokenNotValid, "" } if !token.Valid { log.Error("MidValidToken解析token无效", zap.Error(err)) return TokenNotValid, "" } claims, ok := token.Claims.(*LoginClaims) if !ok { return TokenNotValid, "" } // 校验token key := fmt.Sprintf(rediskey.AppLoginUserToken, claims.UserID) if source == 3 { key = fmt.Sprintf(rediskey.PCLoginUserToken, claims.UserID) } appToken, _ := helper.DefaultRedis.GetString(key) if len(appToken) == 0 { //说明未登入或者过期 return TokenExpire, "" } if appToken != tokenStr { //说明是被t return TokenExpire, "" } return TokenSuccess, strings.Join([]string{utility.IntToString(claims.UserID), claims.NickName, claims.Phone, claims.Email}, ",") } // GetLoginUserJwt 解析用户登入信息 func GetLoginUserJwt(tokenStr string) LoginUserJwt { if len(tokenStr) == 0 { return LoginUserJwt{} } tokenArr := strings.Split(tokenStr, ",") arrLen := len(tokenArr) item := LoginUserJwt{ UserID: utility.StringAsInteger(tokenArr[0]), } if arrLen > 1 { item.NickName = tokenArr[1] } if arrLen > 2 { item.Phone = tokenArr[2] } if arrLen > 3 { item.Email = tokenArr[3] } return item } // AgentLoginJwt ==============Agent 代理商 JWT========================// type AgentLoginJwt struct { AgentId int `json:"agent_id"` // 代理商ID UserId int `json:"user_id"` // 代理商关联的用户ID Name string `json:"name"` // 代理商姓名 Email string `json:"email"` // 代理商邮件 IP string `json:"ip"` // 代理商IP } type AgentLoginClaims struct { AgentId int `json:"agent_id"` // 代理商ID UserId int `json:"user_id"` // 代理商关联的用户ID Name string `json:"name"` // 代理商姓名 Email string `json:"email"` // 代理商邮件 IP string `json:"ip"` // 代理商IP jwt.RegisteredClaims //StandardClaims } var JwtAgentSigningKey = []byte("tokexagent.com") //Jwt signing key // CreateAgentJwtToken 代理商产生的token func CreateAgentJwtToken(userJwt AgentLoginJwt, minute int) string { // 创建一个我们自己的声明 exp := time.Now().Add(time.Minute * time.Duration(minute)) c := AgentLoginClaims{ userJwt.AgentId, userJwt.UserId, // 自定义字段 userJwt.Name, userJwt.Email, userJwt.IP, jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(exp), // 过期时间 Issuer: "Tokex-Agent", // 签发人 }, } // 使用指定的签名方法创建签名对象 token := jwt.NewWithClaims(jwt.SigningMethodHS256, c) tokenStr, err := token.SignedString(JwtAgentSigningKey) if err != nil { log.Error("获取jwt token失败:", zap.Error(err)) return "" } return tokenStr } // MidValidAgentToken 检验token是否有效,返回token解密后的string func MidValidAgentToken(tokenStr string) (int, string) { // 解析token token, err := jwt.ParseWithClaims(tokenStr, &AgentLoginClaims{}, func(token *jwt.Token) (i interface{}, err error) { return JwtAgentSigningKey, nil }) if err != nil { return TokenNotValid, "" } if !token.Valid { log.Error("MidValidAgentToken解析token无效", zap.Error(err)) return TokenNotValid, "" } claims, ok := token.Claims.(*AgentLoginClaims) if !ok { return TokenNotValid, "" } // 校验token key := fmt.Sprintf(rediskey.AgentLoginUserToken, claims.AgentId) appToken, _ := helper.DefaultRedis.GetString(key) if len(appToken) == 0 { return TokenExpire, "" } if appToken != tokenStr { return TokenExpire, "" } return TokenSuccess, strings.Join([]string{utility.IntToString(claims.AgentId), utility.IntToString(claims.UserId), claims.Name, claims.Email, claims.IP}, ",") } // GetLoginAgentJwt 解析代理商登入信息 func GetLoginAgentJwt(tokenStr string) AgentLoginJwt { if len(tokenStr) == 0 { return AgentLoginJwt{} } tokenArr := strings.Split(tokenStr, ",") arrLen := len(tokenArr) item := AgentLoginJwt{ AgentId: utility.StringAsInteger(tokenArr[0]), } if arrLen > 1 { item.UserId = utility.StringAsInteger(tokenArr[1]) } if arrLen > 2 { item.Name = tokenArr[2] } if arrLen > 3 { item.Email = tokenArr[3] } if arrLen > 4 { item.IP = tokenArr[4] } return item } // ========== Admin 专用 JWT ========== // type AdminLogin struct { UserID int `json:"user_id"` Account string `json:"account"` NickName string `json:"nickname"` Phone string `json:"phone"` Email string `json:"email"` IP string `json:"ip"` } type AdminLoginClaims struct { AdminLogin jwt.RegisteredClaims //StandardClaims } var AdminSignedKey = []byte("adm23inTOKexKey:237") // Admin 签名 Key const AdminTokenIssue = "tokexAdmin" // Admin 签发人 // GenerateAdminLoginToken 生成管理员登录 Token func GenerateAdminLoginToken(admin AdminLogin, expires time.Duration) string { exp := time.Now().Add(expires) claims := AdminLoginClaims{ admin, jwt.RegisteredClaims{ ExpiresAt: jwt.NewNumericDate(exp), // 过期时间 Issuer: AdminTokenIssue, // 签发人 }, } // 使用指定的签名方法创建签名对象 jwtToken, err := jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(AdminSignedKey) if err != nil { log.Error("获取 jwtToken 失败:", zap.Error(err)) } return jwtToken } // ParseAdminLoginToken 解析管理员登录 Token func ParseAdminLoginToken(jwtToken string) (pass bool, adminLogin AdminLoginClaims) { // 解析 jwtToken token, err := jwt.ParseWithClaims(jwtToken, &AdminLoginClaims{}, func(token *jwt.Token) (i interface{}, err error) { return AdminSignedKey, nil }) if err != nil { log.Error("解析 jwtToken 失败:", zap.Error(err)) return false, adminLogin } // 判断是否验证通过,并将 Claims => AdminLoginClaims if claims, pass := token.Claims.(*AdminLoginClaims); pass && token.Valid { return pass, *claims } return false, adminLogin }