service/app/mix/service/logic/token.go

173 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package logic
import (
"fmt"
tokenproto "service/api/proto/token/proto"
"service/app/mix/dao"
"service/dbstruct"
"service/library/configcenter"
"service/library/idgenerator"
"service/library/logger"
"strconv"
"time"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
)
type Token struct {
store *dao.Store
cryptoConfig *configcenter.CryptoConfig
}
func NewToken(store *dao.Store, cryptoConfig *configcenter.CryptoConfig) (a *Token) {
a = &Token{
store: store,
cryptoConfig: cryptoConfig,
}
return
}
// Token
func (p *Token) OpCreate(ctx *gin.Context, req *tokenproto.OpCreateReq) error {
req.Token.Ct = time.Now().Unix()
err := p.store.CreateToken(ctx, req.Token)
if err != nil {
logger.Error("CreateToken fail, err: %v", err)
return err
}
return nil
}
func (p *Token) OpDelete(ctx *gin.Context, id int64) error {
err := p.store.DeleteToken(ctx, id)
if err != nil {
logger.Error("DeleteToken fail, err: %v", err)
return err
}
return nil
}
func (p *Token) OpDeleteByMid(ctx *gin.Context, mid int64) error {
err := p.store.DeleteTokenByMid(ctx, mid)
if err != nil {
logger.Error("OpDeleteByMid fail, err: %v", err)
return err
}
return nil
}
func (p *Token) OpDeleteByMids(ctx *gin.Context, mids []int64) error {
err := p.store.DeleteTokenByMids(ctx, mids)
if err != nil {
logger.Error("OpDeleteByMids fail, err: %v", err)
return err
}
return nil
}
func (p *Token) OpList(ctx *gin.Context, req *tokenproto.OpListReq) ([]*dbstruct.Token, error) {
list, err := p.store.GetTokenList(ctx, req)
if err != nil {
logger.Error("GetTokenList fail, err: %v", err)
return make([]*dbstruct.Token, 0), err
}
return list, nil
}
func (p *Token) OpGenerate(ctx *gin.Context, req *tokenproto.OpCreateReq) (token string, err error) {
//token在数据库里的唯一标识
token_uuid := idgenerator.GenTokenId()
//生成token
atClaims := jwt.MapClaims{
"authorized": true,
"token_uuid": token_uuid,
"mid": req.Token.Mid,
}
at := jwt.NewWithClaims(jwt.SigningMethodHS256, atClaims)
token, err = at.SignedString([]byte(p.cryptoConfig.TokenPrivateKey))
if err != nil {
logger.Error("OpGenerate generation of token failed, err: %v", err)
return "", err
}
//将token存入数据库
req.Token.Id = token_uuid
err = p.store.CreateToken(ctx, req.Token)
if err != nil {
logger.Error("OpGenerate failed, err: %v", err)
return "", err
}
return
}
func (p *Token) OpVerify(ctx *gin.Context, tokenString string) error {
//是否携带令牌
if tokenString == "" {
logger.Error("Missing auth token")
return fmt.Errorf("missing auth token")
}
//检查令牌加密方法及签名
token, err := p.OpVerifyCrypto(ctx, tokenString)
if err != nil {
logger.Error("OpVerifyCrypto failed")
return err
}
//检查数据库中是否还存在该token是否还有效
err = p.OpVerifyValid(ctx, token)
if err != nil {
logger.Error("OpVerifyValid failed")
return err
}
return nil
}
// 检查令牌加密方法及签名
func (p *Token) OpVerifyCrypto(ctx *gin.Context, tokenString string) (token *jwt.Token, err error) {
token, err = jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return []byte(p.cryptoConfig.TokenPrivateKey), nil
})
if err != nil {
logger.Error("Parse token failed")
return nil, err
}
return
}
// 检查该token是否还有效
func (p *Token) OpVerifyValid(ctx *gin.Context, token *jwt.Token) error {
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return fmt.Errorf("Token type assertion failed")
}
if !token.Valid {
return fmt.Errorf("Token is invalid")
}
tokenUuid, err := strconv.ParseInt(fmt.Sprintf("%.f", claims["token_uuid"]), 10, 64)
if err != nil {
return fmt.Errorf("failed to acquire token_uuid from token")
}
list, err := p.OpList(ctx, &tokenproto.OpListReq{
Id: tokenUuid,
})
if err != nil {
return fmt.Errorf("OpList failed")
}
if len(list) == 0 {
return fmt.Errorf("登录失效,请重新登录!")
}
return nil
}