package jwt
import (
"errors"
"time"
"github.com/golang-jwt/jwt/v4"
)
type (
TokenOptions struct {
AccessSecret string
AccessExpire int64
Fields map[string]interface{}
}
Token struct {
AccessToken string `json:"access_token"`
AccessExpire int64 `json:"access_expire"`
}
)
func BuildTokens(opt TokenOptions) (Token, error) {
var token Token
now := time.Now().Add(-time.Minute).Unix()
accessToken, err := getJwtToken(opt.AccessSecret, now, opt.AccessExpire, opt.Fields)
if err != nil {
return token, nil
}
token.AccessExpire = now + opt.AccessExpire
token.AccessToken = accessToken
return token, nil
}
// @secretKey: JWT 加解密密钥
// @iat: 时间戳
// @seconds: 过期时间,单位秒
// @payload: 数据载体
func getJwtToken(secretKey string, iat, seconds int64, payload map[string]interface{}) (string, error) {
claims := make(jwt.MapClaims)
claims["exp"] = iat + seconds
claims["iat"] = iat
for k, v := range payload {
claims[k] = v
}
token := jwt.New(jwt.SigningMethodHS256)
token.Claims = claims
return token.SignedString([]byte(secretKey))
}
// ParseToken 解析 JWT
// @tokenString: 加密的token
// @mc: 解密后反写的实体 所以要传地址过去 方便反写
// t : 加密时的密钥
type claims struct {
Mobile string
jwt.MapClaims
}
func ParseToken(tokenString string, t string) (*claims, error) {
mc := &claims{}
// 解析token
token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
return []byte(t), nil
})
if err != nil {
return nil, errors.New("JWT已过期")
}
if token.Valid { // 校验token
return mc, nil
}
return mc, errors.New("token校验失败")
}
主要函数为getJwtToken(生成token)、ParseToken(解密token)
getJwtToken生成token传入了token的密钥、过期时间、想要包含的数据,为了解密后进行使用,这一块主要在登录的时候进行使用,手机号为唯一标识
token, tokenErr := jwt.BuildTokens(jwt.TokenOptions{
AccessSecret: l.svcCtx.Config.Auth.AccessSecret,
AccessExpire: l.svcCtx.Config.Auth.AccessExpire,
Fields: map[string]interface{}{
"mobile": req.Mobile,
},
})
ParseToken解密token接受加密后的token、密钥,解出来的就是当时加密想要包含的数据
这一块是中间件中进行了使用,将token解密后,拿到唯一标识,去redis中获取,如果存在说明么有过期,如果不存在,还没有写 哈哈 ,做个笔记 自己记录一下
package middleware
import (
"fmt"
"go/application/basics/internal/config"
"go/application/basics/service/redisClient"
"go/pkg/jwt"
"net/http"
)
type AuthInterceptorMiddleware struct {
}
func NewAuthInterceptorMiddleware() *AuthInterceptorMiddleware {
return &AuthInterceptorMiddleware{}
}
func (m *AuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// TODO generate middleware implement function, delete after code implementation
authRequest := r.Header.Get("Authorization")
if authRequest == "" {
w.WriteHeader(http.StatusAccepted)
w.Write([]byte("请登录"))
return
}
authParse, authErr := jwt.ParseToken(authRequest, config.GlobalConfig.Auth.AccessSecret)
if authErr != nil {
w.WriteHeader(http.StatusAccepted)
w.Write([]byte(authErr.Error()))
}
redis := redisClient.Init(config.GlobalConfig)
fmt.Println("redis--------------------------")
fmt.Println(redis)
val, redisErr := redis.Get(authParse.Mobile).Result()
fmt.Println(val)
fmt.Println(redisErr)
// Passthrough to next handler if need
next(w, r)
}
}
?