This commit is contained in:
2025-02-06 11:14:33 +08:00
commit 07847a2d9e
535 changed files with 65131 additions and 0 deletions

View File

@ -0,0 +1,88 @@
package aeshelper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/md5"
"crypto/rand"
"encoding/base64"
"io"
)
// Encrypt text with the passphrase
func Encrypt(text string, passphrase string) string {
salt := make([]byte, 8)
if _, err := io.ReadFull(rand.Reader, salt); err != nil {
panic(err.Error())
}
key, iv := DeriveKeyAndIv(passphrase, string(salt))
block, err := aes.NewCipher([]byte(key))
if err != nil {
panic(err)
}
pad := PKCS7Padding([]byte(text), block.BlockSize())
ecb := cipher.NewCBCEncrypter(block, []byte(iv))
encrypted := make([]byte, len(pad))
ecb.CryptBlocks(encrypted, pad)
return base64.StdEncoding.EncodeToString([]byte("Salted__" + string(salt) + string(encrypted)))
}
// Decrypt encrypted text with the passphrase
func Decrypt(encrypted string, passphrase string) string {
ct, _ := base64.StdEncoding.DecodeString(encrypted)
if len(ct) < 16 || string(ct[:8]) != "Salted__" {
return ""
}
salt := ct[8:16]
ct = ct[16:]
key, iv := DeriveKeyAndIv(passphrase, string(salt))
block, err := aes.NewCipher([]byte(key))
if err != nil {
panic(err)
}
cbc := cipher.NewCBCDecrypter(block, []byte(iv))
dst := make([]byte, len(ct))
cbc.CryptBlocks(dst, ct)
return string(PKCS7Trimming(dst))
}
// PKCS7Padding PKCS7Padding
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
// PKCS7Trimming PKCS7Trimming
func PKCS7Trimming(encrypt []byte) []byte {
padding := encrypt[len(encrypt)-1]
return encrypt[:len(encrypt)-int(padding)]
}
// DeriveKeyAndIv DeriveKeyAndIv
func DeriveKeyAndIv(passphrase string, salt string) (string, string) {
salted := ""
dI := ""
for len(salted) < 48 {
md := md5.New()
md.Write([]byte(dI + passphrase + salt))
dM := md.Sum(nil)
dI = string(dM[:16])
salted = salted + dI
}
key := salted[0:32]
iv := salted[32:48]
return key, iv
}

View File

@ -0,0 +1,107 @@
package aeshelper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"encoding/hex"
"github.com/forgoer/openssl"
)
const (
sKey = "ptQJqRKxICCTeo6w" // "dde4b1f8a9e6b814"
ivParameter = "O3vZvOJSnQDP9hKT" // "dde4b1f8a9e6b814"
)
// PswEncrypt 加密
func PswEncrypt(src string) (string, error) {
key := []byte(sKey)
iv := []byte(ivParameter)
result, err := Aes128Encrypt([]byte(src), key, iv)
if err != nil {
return "", err
}
return base64.RawStdEncoding.EncodeToString(result), nil
}
// PswDecrypt 解密
func PswDecrypt(src string) (string, error) {
key := []byte(sKey)
iv := []byte(ivParameter)
var result []byte
var err error
result, err = base64.StdEncoding.DecodeString(src)
if err != nil {
return "", err
}
origData, err := Aes128Decrypt(result, key, iv)
if err != nil {
return "", err
}
return string(origData), nil
}
func Aes128Encrypt(origData, key []byte, IV []byte) ([]byte, error) {
if key == nil || len(key) != 16 {
return nil, nil
}
if IV != nil && len(IV) != 16 {
return nil, nil
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
origData = PKCS5Padding(origData, blockSize)
blockMode := cipher.NewCBCEncrypter(block, IV[:blockSize])
crypted := make([]byte, len(origData))
// 根据CryptBlocks方法的说明如下方式初始化crypted也可以
blockMode.CryptBlocks(crypted, origData)
return crypted, nil
}
func Aes128Decrypt(crypted, key []byte, IV []byte) ([]byte, error) {
if key == nil || len(key) != 16 {
return nil, nil
}
if IV != nil && len(IV) != 16 {
return nil, nil
}
block, err := aes.NewCipher(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
blockMode := cipher.NewCBCDecrypter(block, IV[:blockSize])
origData := make([]byte, len(crypted))
blockMode.CryptBlocks(origData, crypted)
origData = PKCS5UnPadding(origData)
return origData, nil
}
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
padding := blockSize - len(ciphertext)%blockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(ciphertext, padtext...)
}
func PKCS5UnPadding(origData []byte) []byte {
length := len(origData)
// 去掉最后一个字节 unpadding 次
unpadding := int(origData[length-1])
return origData[:(length - unpadding)]
}
// 密码加密
func AesEcbEncrypt(origData string) string {
//加密
dst, _ := openssl.AesECBEncrypt([]byte(origData), []byte(sKey), openssl.PKCS7_PADDING)
return hex.EncodeToString(dst)
}
// 密码解密
func AesEcbDecrypt(origData string) string {
value, _ := hex.DecodeString(origData)
dst, _ := openssl.AesECBDecrypt(value, []byte(sKey), openssl.PKCS7_PADDING)
return string(dst)
}

View File

@ -0,0 +1,65 @@
package aeshelper
import (
"encoding/json"
"fmt"
"testing"
"time"
)
// 测试加密解密
func Test_EnDe(t *testing.T) {
a := `asg`
b := Encrypt(a, `code_verify_success`)
c := Decrypt(b, `code_verify_success`)
fmt.Println(`原始为`, a)
fmt.Println(`加密后`, b)
fmt.Println(`解密后`, c)
}
func TestAesEcbEncrypt(t *testing.T) {
//aes := AesEcbEncrypt("123456")
aes := AesEcbEncrypt(fmt.Sprintf("%v_%v", time.Now().Unix(), 1332355333))
dst := AesEcbDecrypt(aes)
fmt.Println(aes)
fmt.Println(dst)
}
// TODO:需要加密的接口
/**
1.合约下单接口 /api/futures/trade/order
2.合约撤单 /api/futures/trade/cancelorder
3.调整保证金 /api/futures/trade/adjustmargin
4.变换逐全仓模式 /api/futures/trade/marginType
5.更改持仓模式(方向) /api/futures/trade/positionSide/dual
6.资产划转 /api/futures/transfer
*/
func TestAesEcbEncryptOrder(t *testing.T) {
data := addFutOrderReq{
OrderType: 1,
BuyType: 3,
TriggerDecide: 3,
IsReduce: 2,
Coin: "asdf",
Price: "333.23",
Num: "23.20",
TriggerPrice: "1.023",
PositionSide: "long",
}
b, _ := json.Marshal(data)
aes := AesEcbEncrypt(string(b))
dst := AesEcbDecrypt(aes)
fmt.Println(aes)
fmt.Println(dst)
}
type addFutOrderReq struct {
OrderType int `json:"order_type"` // 订单类型1限价2限价止盈止损3市价,4市价止盈止损,5强平委托(就是限价委托)
BuyType int `json:"buy_type"` // 买卖类型1买2卖
TriggerDecide int `json:"trigger_decide"` // 触发条件 1按最新成交价格算2按标记价格算
IsReduce int `json:"is_reduce"` // 1是只减仓位(点击仓位列表中的平仓按钮)0正常
Coin string `json:"coin"` // 交易币
Price string `json:"price"` // 下单价格(限价+止盈止损时,该字段必填)
Num string `json:"num"` // 下单数量(市价时该字段必填)
TriggerPrice string `json:"trigger_price"` // 触发价格
PositionSide string `json:"position_side"` // 持仓方向单向持仓模式下可填both;在双向持仓模式下必填,且仅可选择 long 或 short
}

View File

@ -0,0 +1,94 @@
package aesoldhelper
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"errors"
"io"
"strings"
)
func addBase64Padding(value string) string {
m := len(value) % 4
if m != 0 {
value += strings.Repeat("=", 4-m)
}
return value
}
func removeBase64Padding(value string) string {
return strings.Replace(value, "=", "", -1)
}
// Pad Pad
func Pad(src []byte) []byte {
padding := aes.BlockSize - len(src)%aes.BlockSize
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
return append(src, padtext...)
}
// Unpad Unpad
func Unpad(src []byte) ([]byte, error) {
length := len(src)
unpadding := int(src[length-1])
if unpadding > length {
return nil, errors.New("unpad error. This could happen when incorrect encryption key is used")
}
return src[:(length - unpadding)], nil
}
// AesEncrypt AesEncrypt
func AesEncrypt(key []byte, text string) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
msg := Pad([]byte(text))
ciphertext := make([]byte, aes.BlockSize+len(msg))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
return "", err
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(msg))
finalMsg := removeBase64Padding(base64.URLEncoding.EncodeToString(ciphertext))
return finalMsg, nil
}
// AesDecrypt AesDecrypt
func AesDecrypt(key []byte, text string) (string, error) {
block, err := aes.NewCipher(key)
if err != nil {
return "", err
}
decodedMsg, err := base64.URLEncoding.DecodeString(addBase64Padding(text))
if err != nil {
return "", err
}
if (len(decodedMsg) % aes.BlockSize) != 0 {
return "", errors.New("blocksize must be multipe of decoded message length")
}
iv := decodedMsg[:aes.BlockSize]
msg := decodedMsg[aes.BlockSize:]
cfb := cipher.NewCFBDecrypter(block, iv)
cfb.XORKeyStream(msg, msg)
unpadMsg, err := Unpad(msg)
if err != nil {
return "", err
}
return string(unpadMsg), nil
}

View File

@ -0,0 +1,19 @@
package aeshelper
var (
apiaeskey = "9jxFTkydwCJsmIA1TUrv"
)
// EncryptApi 加密apikey
func EncryptApi(apikey, secretkey string) (apikeyen, secrekeyen string) {
apikeyen = Encrypt(apikey, apiaeskey)
secrekeyen = Encrypt(secretkey, apiaeskey)
return apikeyen, secrekeyen
}
// DecryptApi 解密apikey
func DecryptApi(apikeyen, secrekeyen string) (apikey, secrekey string) {
apikey = Decrypt(apikeyen, apiaeskey)
secrekey = Decrypt(secrekeyen, apiaeskey)
return apikey, secrekey
}

View File

@ -0,0 +1,133 @@
package inttostring
import (
"math"
"math/rand"
"strings"
"time"
)
// IntToStr 用于将数字映射为字符串 例如 用户id-->邀请码
type IntToStr struct {
SALT int // 随意取一个数值
Len int // 邀请码长度
PRIME2 byte // 与邀请码长度 8 互质
AlphanumericSet []rune
PRIME1 int // 与字符集长度 36 互质
}
var (
Invite = NewInvite() // 邀请码
)
// NewInvite 邀请码
func NewInvite() *IntToStr {
return &IntToStr{
SALT: 15151239, // 随意取一个数值
Len: 8, // 邀请码长度
PRIME2: 3, // 与邀请码长度 Len 互质
AlphanumericSet: []rune{
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
}, // 邀请码长度
PRIME1: 5, // 与字符集长度 36 互质
}
}
func (in IntToStr) DeCode(codeStr string) int {
code := make([]rune, 0, in.Len)
var key rune = 0
// 还原k
for i := 0; i < in.Len; i++ {
for k, v := range in.AlphanumericSet {
if v == rune(codeStr[i]) {
key = rune(k)
break
}
}
code = append(code, key)
}
code2 := make([]rune, 0, in.Len)
// 还原顺序
for i := 0; i < in.Len; i++ {
idx := i * int(in.PRIME2) % in.Len
code2 = append(code2, code[idx])
}
// 还原数字
var x int
for i := 0; i < in.Len; i++ {
code2[i] = (code2[i] - rune(i)*code2[0]) % rune(len(in.AlphanumericSet))
code2[i] = (code2[i] + rune(len(in.AlphanumericSet))) % rune(len(in.AlphanumericSet))
place := math.Pow(float64(len(in.AlphanumericSet)), float64(i)) // 次方运算
x += int(code2[i]) * int(place)
}
// 去盐 + 缩小
x = (x - in.SALT) / in.PRIME1
return x
}
func (in IntToStr) Encode(uid int) string {
// 放大 + 加盐
uid = uid*in.PRIME1 + in.SALT
slIdx := make([]byte, in.Len)
// 扩散
for i := 0; i < in.Len; i++ {
slIdx[i] = byte(uid % len(in.AlphanumericSet)) // 转换进制 获取36进制的每一位值
slIdx[i] = (slIdx[i] + byte(i)*slIdx[0]) % byte(len(in.AlphanumericSet)) // 其他位与个位加和再取余(让个位的变化影响到所有位)
uid = uid / len(in.AlphanumericSet) // 相当于右移一位62进制
}
var code []rune
// 混淆
for i := 0; i < in.Len; i++ {
idx := (byte(i) * in.PRIME2) % byte(in.Len)
code = append(code, in.AlphanumericSet[slIdx[idx]])
}
return string(code)
}
const letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
const smsLetters = "0123456789"
// GenerateRandomString 生成指定长度的随机字符串
func GenerateRandomString(n int) string {
rand.Seed(time.Now().UnixNano()) // 初始化随机数种子
result := make([]byte, n)
for i := range result {
result[i] = letters[rand.Intn(len(letters))]
}
return string(result)
}
// GenerateRandomSmsString 生成指定长度的随机字符串
func GenerateRandomSmsString(n int) string {
rand.Seed(time.Now().UnixNano()) // 初始化随机数种子
result := make([]byte, n)
for i := range result {
result[i] = smsLetters[rand.Intn(len(smsLetters))]
}
return string(result)
}
func EncryptString(s string, prefixLen, suffixLen int) string {
length := len(s)
// 如果字符串长度不足,直接返回原字符串
if length <= prefixLen+suffixLen {
return s
}
// 保留前 prefixLen 位和后 suffixLen 位
prefix := s[:prefixLen]
suffix := s[length-suffixLen:]
// 中间部分用 * 替换
middle := strings.Repeat("*", 6)
// 拼接结果
return prefix + middle + suffix
}

View File

@ -0,0 +1,33 @@
package inttostring
import (
"fmt"
"testing"
)
func Test_a(t *testing.T) {
a:=1156
// b:=byte(a)
fmt.Println(a%10)
}
// 加密解密
func Test_EnDecode(t *testing.T) {
uid := 6515461646
Invi := NewInvite()
encode := Invi.Encode(uid)
DeCode := Invi.DeCode(encode)
fmt.Println(`原始为`, uid)
fmt.Println(`加密后`, encode)
fmt.Println(`解密后`, DeCode)
}
func Test_Invite(t *testing.T) {
for uid := 0; uid < 10000000; uid++ {
encode := Invite.Encode(uid)
DeCode := Invite.DeCode(encode)
if DeCode != uid {
t.Fatal(`加密解密错误`, DeCode, uid)
}
}
}

View File

@ -0,0 +1,295 @@
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
}

View File

@ -0,0 +1,17 @@
package md5helper
import (
"crypto/md5"
"encoding/hex"
)
// MD5 md5加密
func MD5(input string) string {
cc := md5.Sum([]byte(input))
return hex.EncodeToString(cc[:])
}
// MD52 md52次
func MD52(input string) string {
return MD5(MD5(input))
}

View File

@ -0,0 +1,55 @@
package md5helper
import (
"crypto/md5"
"encoding/hex"
"fmt"
"testing"
)
func TestMD52(t *testing.T) {
got := MD52("Qq123456")
fmt.Println(got)
}
func TestMD5(t *testing.T) {
got := []byte("Qq123456")
s := md5.New()
s.Write(got)
fmt.Println(hex.EncodeToString(s.Sum(nil)))
cc := md5.Sum(got)
fmt.Println(hex.EncodeToString(cc[:]))
fmt.Printf("%x\n", md5.Sum(got))
}
// go test -bench=_QE_ -benchmem -run=^$
func Benchmark_QE_1(b *testing.B) {
for i := 0; i < b.N; i++ {
input := `Qq123456`
s := md5.New()
s.Write([]byte(input))
hex.EncodeToString(s.Sum(nil))
}
}
func Benchmark_QE_2(b *testing.B) {
for i := 0; i < b.N; i++ {
input := `Qq123456`
cc := md5.Sum([]byte(input))
hex.EncodeToString(cc[:])
}
}
func Benchmark_QE_3(b *testing.B) {
for i := 0; i < b.N; i++ {
input := `Qq123456`
fmt.Sprintf("%x\n", md5.Sum([]byte(input)))
}
}
// Benchmark_QE_1-6 6354160 189.8 ns/op 48 B/op 2 allocs/op
// Benchmark_QE_2-6 7352328 162.9 ns/op 32 B/op 1 allocs/op
// Benchmark_QE_3-6 3007480 396.9 ns/op 80 B/op 3 allocs/op