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