296 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			296 lines
		
	
	
		
			8.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
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
 | 
						||
}
 |