jwt.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package admin
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/dgrijalva/jwt-go"
  6. "github.com/gin-gonic/gin"
  7. "net/http"
  8. "strconv"
  9. "strings"
  10. "time"
  11. "ulink-admin/config"
  12. "ulink-admin/frame"
  13. "ulink-admin/modules/system/models/model"
  14. "ulink-admin/pkg/jwt/common"
  15. )
  16. // JWTAuth 中间件,检查token
  17. func JWTAuth() frame.IMidHandler {
  18. return func(c *frame.Context) {
  19. //调用过滤去将放行的请求先放行
  20. if DoSquare(c.Context) {
  21. return
  22. }
  23. token := c.Request.Header.Get("Authorization")
  24. if token == "" {
  25. c.JSON(http.StatusOK, gin.H{
  26. "status": 401,
  27. "msg": "请求未携带token,无权限访问",
  28. })
  29. c.Abort()
  30. return
  31. }
  32. s := strings.Split(token, " ")
  33. if len(s) != 2 {
  34. c.JSON(http.StatusOK, gin.H{
  35. "status": 401,
  36. "msg": "token格式错误,无权限访问",
  37. })
  38. c.Abort()
  39. return
  40. }
  41. j := NewJWT()
  42. // parseToken 解析token包含的信息
  43. claims, err := j.ParseToken(s[1])
  44. if err != nil {
  45. c.JSON(http.StatusOK, gin.H{
  46. "status": 401,
  47. "msg": err.Error(),
  48. })
  49. c.Abort()
  50. return
  51. }
  52. appServer := config.GetServerCfg()
  53. lock := appServer.Lock
  54. if lock == "0" {
  55. get, err := GetToken(claims.RedisKey)
  56. //base.RedisDB.GET(claims.RedisKey)
  57. if err == nil {
  58. if !(get == s[1]) {
  59. c.JSON(http.StatusOK, gin.H{
  60. "status": 401,
  61. "msg": "您的账号已在其他终端登录,请重新登录",
  62. })
  63. c.Abort()
  64. return
  65. }
  66. }
  67. }
  68. if err != nil {
  69. c.JSON(http.StatusOK, gin.H{
  70. "status": 401,
  71. "msg": err.Error(),
  72. })
  73. c.Abort()
  74. return
  75. }
  76. // 继续交由下一个路由处理,并将解析出的信息传递下去
  77. c.Set("claims", claims)
  78. }
  79. }
  80. // JWT 签名结构
  81. type JWT struct {
  82. SigningKey []byte
  83. }
  84. // 一些常量
  85. var (
  86. TokenExpired = errors.New("授权已过期")
  87. TokenNotValidYet = errors.New("token not active yet")
  88. TokenMalformed = errors.New("令牌非法")
  89. TokenInvalid = errors.New("couldn't handle this token")
  90. SignKey = "0df9b8db-6f7c-d713-eeab-ecb317696042"
  91. userTypes = map[string]string{"00": "SystemUser:", "01": "WechatUser:"}
  92. )
  93. // CustomClaims 载荷,可以加一些自己需要的信息
  94. type CustomClaims struct {
  95. UserInfo *model.SysUser `json:"userInfo"`
  96. jwt.StandardClaims
  97. RedisKey string
  98. RedisTimeOut int
  99. }
  100. // NewJWT 新建一个jwt实例
  101. func NewJWT() *JWT {
  102. return &JWT{
  103. []byte(GetSignKey()),
  104. }
  105. }
  106. // GetSignKey 获取signKey
  107. func GetSignKey() string {
  108. return SignKey
  109. }
  110. // SetSignKey 设置SignKey
  111. func SetSignKey(key string) string {
  112. SignKey = key
  113. return SignKey
  114. }
  115. // CreateToken 生成一个token
  116. func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
  117. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  118. return token.SignedString(j.SigningKey)
  119. }
  120. // CreateUserToken 生成含有用户信息的token
  121. func (j *JWT) CreateUserToken(loginType string, u *model.SysUser) (string, error) {
  122. userType := userTypes[u.UserType]
  123. if userType == "" {
  124. return "", errors.New("用户类型错误")
  125. }
  126. jwtConfig := config.GetJwtConfig()
  127. strInt64 := strconv.FormatInt(jwtConfig.TimeOut.Nanoseconds()*3600, 10)
  128. sec, _ := strconv.Atoi(strInt64)
  129. claims := jwt.NewWithClaims(jwt.SigningMethodHS256, CustomClaims{
  130. UserInfo: u,
  131. StandardClaims: jwt.StandardClaims{
  132. //设置token小时时效
  133. ExpiresAt: time.Now().Add(jwtConfig.TimeOut * time.Hour).Unix(),
  134. IssuedAt: time.Now().Unix(),
  135. Issuer: jwtConfig.Issuer,
  136. },
  137. RedisKey: fmt.Sprintf("%s|%s|%s", common.LOGIN_ADMIN, loginType, u.UserName),
  138. RedisTimeOut: sec,
  139. })
  140. return claims.SignedString(j.SigningKey)
  141. }
  142. // ParseToken 解析Token
  143. func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {
  144. token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  145. return j.SigningKey, nil
  146. })
  147. if err != nil {
  148. if ve, ok := err.(*jwt.ValidationError); ok {
  149. if ve.Errors&jwt.ValidationErrorMalformed != 0 {
  150. return nil, TokenMalformed
  151. } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
  152. // Token is expired
  153. return nil, TokenExpired
  154. } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
  155. return nil, TokenNotValidYet
  156. } else {
  157. return nil, TokenInvalid
  158. }
  159. }
  160. }
  161. if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
  162. return claims, nil
  163. }
  164. return nil, TokenInvalid
  165. }
  166. // RefreshToken 更新token
  167. func (j *JWT) RefreshToken(tokenString string) (string, error) {
  168. jwt.TimeFunc = func() time.Time {
  169. return time.Unix(0, 0)
  170. }
  171. token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  172. return j.SigningKey, nil
  173. })
  174. if err != nil {
  175. return "", err
  176. }
  177. if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
  178. jwt.TimeFunc = time.Now
  179. claims.StandardClaims.ExpiresAt = time.Now().Add(24 * time.Hour).Unix()
  180. return j.CreateToken(*claims)
  181. }
  182. return "", TokenInvalid
  183. }