123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- package admin
- import (
- "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 中间件,检查token
- func 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 获取signKey
- func GetSignKey() string {
- return SignKey
- }
- // SetSignKey 设置SignKey
- func SetSignKey(key string) string {
- SignKey = key
- return SignKey
- }
- // CreateToken 生成一个token
- func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
- token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
- return token.SignedString(j.SigningKey)
- }
- // CreateUserToken 生成含有用户信息的token
- func (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 解析Token
- func (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 更新token
- func (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
- }
|