| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 | package adminimport (	"errors"	"fmt"	"github.com/dgrijalva/jwt-go"	"github.com/gin-gonic/gin"	"net/http"	"strconv"	"strings"	"time"	"ulink-admin/config"	"ulink-admin/frame"	"ulink-admin/modules/system/models/model"	"ulink-admin/pkg/jwt/common")// JWTAuth 中间件,检查tokenfunc JWTAuth() frame.IMidHandler {	return func(c *frame.Context) {		//调用过滤去将放行的请求先放行		if DoSquare(c.Context) {			return		}		token := c.Request.Header.Get("Authorization")		if token == "" {			c.JSON(http.StatusOK, gin.H{				"status": 401,				"msg":    "请求未携带token,无权限访问",			})			c.Abort()			return		}		s := strings.Split(token, " ")		if len(s) != 2 {			c.JSON(http.StatusOK, gin.H{				"status": 401,				"msg":    "token格式错误,无权限访问",			})			c.Abort()			return		}		j := NewJWT()		// parseToken 解析token包含的信息		claims, err := j.ParseToken(s[1])		if err != nil {			c.JSON(http.StatusOK, gin.H{				"status": 401,				"msg":    err.Error(),			})			c.Abort()			return		}		appServer := config.GetServerCfg()		lock := appServer.Lock		if lock == "0" {			get, err := GetToken(claims.RedisKey)			//base.RedisDB.GET(claims.RedisKey)			if err == nil {				if !(get == s[1]) {					c.JSON(http.StatusOK, gin.H{						"status": 401,						"msg":    "您的账号已在其他终端登录,请重新登录",					})					c.Abort()					return				}			}		}		if err != nil {			c.JSON(http.StatusOK, gin.H{				"status": 401,				"msg":    err.Error(),			})			c.Abort()			return		}		// 继续交由下一个路由处理,并将解析出的信息传递下去		c.Set("claims", claims)	}}// JWT 签名结构type JWT struct {	SigningKey []byte}// 一些常量var (	TokenExpired     = errors.New("授权已过期")	TokenNotValidYet = errors.New("token not active yet")	TokenMalformed   = errors.New("令牌非法")	TokenInvalid     = errors.New("couldn't handle this token")	SignKey          = "0df9b8db-6f7c-d713-eeab-ecb317696042"	userTypes        = map[string]string{"00": "SystemUser:", "01": "WechatUser:"})// CustomClaims 载荷,可以加一些自己需要的信息type CustomClaims struct {	UserInfo *model.SysUser `json:"userInfo"`	jwt.StandardClaims	RedisKey     string	RedisTimeOut int}// NewJWT 新建一个jwt实例func NewJWT() *JWT {	return &JWT{		[]byte(GetSignKey()),	}}// GetSignKey 获取signKeyfunc GetSignKey() string {	return SignKey}// SetSignKey 设置SignKeyfunc SetSignKey(key string) string {	SignKey = key	return SignKey}// CreateToken 生成一个tokenfunc (j *JWT) CreateToken(claims CustomClaims) (string, error) {	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)	return token.SignedString(j.SigningKey)}// CreateUserToken 生成含有用户信息的tokenfunc (j *JWT) CreateUserToken(loginType string, u *model.SysUser) (string, error) {	userType := userTypes[u.UserType]	if userType == "" {		return "", errors.New("用户类型错误")	}	jwtConfig := config.GetJwtConfig()	strInt64 := strconv.FormatInt(jwtConfig.TimeOut.Nanoseconds()*3600, 10)	sec, _ := strconv.Atoi(strInt64)	claims := jwt.NewWithClaims(jwt.SigningMethodHS256, CustomClaims{		UserInfo: u,		StandardClaims: jwt.StandardClaims{			//设置token小时时效			ExpiresAt: time.Now().Add(jwtConfig.TimeOut * time.Hour).Unix(),			IssuedAt:  time.Now().Unix(),			Issuer:    jwtConfig.Issuer,		},		RedisKey:     fmt.Sprintf("%s|%s|%s", common.LOGIN_ADMIN, loginType, u.UserName),		RedisTimeOut: sec,	})	return claims.SignedString(j.SigningKey)}// ParseToken 解析Tokenfunc (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {	token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {		return j.SigningKey, nil	})	if err != nil {		if ve, ok := err.(*jwt.ValidationError); ok {			if ve.Errors&jwt.ValidationErrorMalformed != 0 {				return nil, TokenMalformed			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {				// Token is expired				return nil, TokenExpired			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {				return nil, TokenNotValidYet			} else {				return nil, TokenInvalid			}		}	}	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {		return claims, nil	}	return nil, TokenInvalid}// RefreshToken 更新tokenfunc (j *JWT) RefreshToken(tokenString string) (string, error) {	jwt.TimeFunc = func() time.Time {		return time.Unix(0, 0)	}	token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {		return j.SigningKey, nil	})	if err != nil {		return "", err	}	if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {		jwt.TimeFunc = time.Now		claims.StandardClaims.ExpiresAt = time.Now().Add(24 * time.Hour).Unix()		return j.CreateToken(*claims)	}	return "", TokenInvalid}
 |