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
							 | 
						|||
| 
								 | 
							
								}
							 |