From c3f921d37ae14cb2a42e7aa7a9ba7b75447da992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=92=8B=E5=90=89=E5=85=86?= <303176530@qq.com> Date: Wed, 1 Sep 2021 23:06:25 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E5=8D=87=E6=80=A7=E8=83=BD=20?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=89=8D=E7=AB=AFtab=E9=A1=B5=E9=9D=A2bug=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0ws=E6=8F=92=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- server/api/v1/system/sys_user.go | 5 +- server/go.mod | 2 + server/middleware/jwt.go | 100 ++---------------- server/utils/jwt.go | 71 +++++++++++++ web/package.json | 2 +- .../layout/aside/historyComponent/history.vue | 17 +-- web/src/view/layout/index.vue | 1 + 7 files changed, 97 insertions(+), 101 deletions(-) create mode 100644 server/utils/jwt.go diff --git a/server/api/v1/system/sys_user.go b/server/api/v1/system/sys_user.go index 1652523f..060d368c 100644 --- a/server/api/v1/system/sys_user.go +++ b/server/api/v1/system/sys_user.go @@ -5,7 +5,6 @@ import ( "time" "github.com/flipped-aurora/gin-vue-admin/server/global" - "github.com/flipped-aurora/gin-vue-admin/server/middleware" "github.com/flipped-aurora/gin-vue-admin/server/model/common/request" "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" "github.com/flipped-aurora/gin-vue-admin/server/model/system" @@ -47,7 +46,7 @@ func (b *BaseApi) Login(c *gin.Context) { // 登录以后签发jwt func (b *BaseApi) tokenNext(c *gin.Context, user system.SysUser) { - j := &middleware.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名 + j := &utils.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名 claims := systemReq.CustomClaims{ UUID: user.UUID, ID: user.ID, @@ -210,7 +209,7 @@ func (b *BaseApi) SetUserAuthority(c *gin.Context) { response.FailWithMessage(err.Error(), c) } else { claims := utils.GetUserInfo(c) - j := &middleware.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名 + j := &utils.JWT{SigningKey: []byte(global.GVA_CONFIG.JWT.SigningKey)} // 唯一签名 claims.AuthorityId = sua.AuthorityId if token, err := j.CreateToken(*claims); err != nil { global.GVA_LOG.Error("修改失败!", zap.Any("err", err)) diff --git a/server/go.mod b/server/go.mod index e9aab535..58369fe1 100644 --- a/server/go.mod +++ b/server/go.mod @@ -9,6 +9,7 @@ require ( github.com/casbin/gorm-adapter/v3 v3.0.2 github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/flipped-aurora/gva-plugins v0.0.0-20210828060501-fc8b729b9a4a + github.com/flipped-aurora/ws v1.0.2 github.com/fsnotify/fsnotify v1.4.9 github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 github.com/gin-gonic/gin v1.6.3 @@ -22,6 +23,7 @@ require ( github.com/robfig/cron/v3 v3.0.1 github.com/satori/go.uuid v1.2.0 github.com/shirou/gopsutil v3.21.1+incompatible + github.com/songzhibin97/gkit v1.1.1 github.com/spf13/viper v1.7.0 github.com/swaggo/gin-swagger v1.3.0 github.com/swaggo/swag v1.7.0 diff --git a/server/middleware/jwt.go b/server/middleware/jwt.go index 3eb701ad..adf82791 100644 --- a/server/middleware/jwt.go +++ b/server/middleware/jwt.go @@ -1,17 +1,15 @@ package middleware import ( - "errors" + "github.com/flipped-aurora/gin-vue-admin/server/utils" "strconv" "time" "github.com/flipped-aurora/gin-vue-admin/server/global" "github.com/flipped-aurora/gin-vue-admin/server/model/common/response" "github.com/flipped-aurora/gin-vue-admin/server/model/system" - "github.com/flipped-aurora/gin-vue-admin/server/model/system/request" "github.com/flipped-aurora/gin-vue-admin/server/service" - "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" "go.uber.org/zap" ) @@ -32,11 +30,11 @@ func JWTAuth() gin.HandlerFunc { c.Abort() return } - j := NewJWT() + j := utils.NewJWT() // parseToken 解析token包含的信息 claims, err := j.ParseToken(token) if err != nil { - if err == TokenExpired { + if err == utils.TokenExpired { response.FailWithDetailed(gin.H{"reload": true}, "授权已过期", c) c.Abort() return @@ -45,11 +43,12 @@ func JWTAuth() gin.HandlerFunc { c.Abort() return } - if err, _ = userService.FindUserByUuid(claims.UUID.String()); err != nil { - _ = jwtService.JsonInBlacklist(system.JwtBlacklist{Jwt: token}) - response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) - c.Abort() - } + // 用户被删除的逻辑 需要优化 此处比较消耗性能 如果需要 请自行打开 + //if err, _ = userService.FindUserByUuid(claims.UUID.String()); err != nil { + // _ = jwtService.JsonInBlacklist(system.JwtBlacklist{Jwt: token}) + // response.FailWithDetailed(gin.H{"reload": true}, err.Error(), c) + // c.Abort() + //} if claims.ExpiresAt-time.Now().Unix() < claims.BufferTime { claims.ExpiresAt = time.Now().Unix() + global.GVA_CONFIG.JWT.ExpiresTime newToken, _ := j.CreateTokenByOldToken(token, *claims) @@ -72,84 +71,3 @@ func JWTAuth() gin.HandlerFunc { } } -type JWT struct { - SigningKey []byte -} - -var ( - TokenExpired = errors.New("Token is expired") - TokenNotValidYet = errors.New("Token not active yet") - TokenMalformed = errors.New("That's not even a token") - TokenInvalid = errors.New("Couldn't handle this token:") -) - -func NewJWT() *JWT { - return &JWT{ - []byte(global.GVA_CONFIG.JWT.SigningKey), - } -} - -// 创建一个token -func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) { - token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return token.SignedString(j.SigningKey) -} - -// CreateTokenByOldToken 旧token 换新token 使用归并回源避免并发问题 -func (j *JWT) CreateTokenByOldToken(oldToken string, claims request.CustomClaims) (string, error) { - v, err, _ := global.GVA_Concurrency_Control.Do("JWT:"+oldToken, func() (interface{}, error) { - return j.CreateToken(claims) - }) - return v.(string), err -} - -// 解析 token -func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) { - token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e 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 token != nil { - if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid { - return claims, nil - } - return nil, TokenInvalid - - } else { - return nil, TokenInvalid - - } - -} - -// 更新token -//func (j *JWT) RefreshToken(tokenString string) (string, error) { -// jwt.TimeFunc = func() time.Time { -// return time.Unix(0, 0) -// } -// token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) { -// return j.SigningKey, nil -// }) -// if err != nil { -// return "", err -// } -// if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid { -// jwt.TimeFunc = time.Now -// claims.StandardClaims.ExpiresAt = time.Now().Unix() + 60*60*24*7 -// return j.CreateToken(*claims) -// } -// return "", TokenInvalid -//} diff --git a/server/utils/jwt.go b/server/utils/jwt.go new file mode 100644 index 00000000..a8d43d23 --- /dev/null +++ b/server/utils/jwt.go @@ -0,0 +1,71 @@ +package utils + +import ( + "errors" + "github.com/dgrijalva/jwt-go" + "github.com/flipped-aurora/gin-vue-admin/server/global" + "github.com/flipped-aurora/gin-vue-admin/server/model/system/request" +) + +type JWT struct { + SigningKey []byte +} + +var ( + TokenExpired = errors.New("Token is expired") + TokenNotValidYet = errors.New("Token not active yet") + TokenMalformed = errors.New("That's not even a token") + TokenInvalid = errors.New("Couldn't handle this token:") +) + +func NewJWT() *JWT { + return &JWT{ + []byte(global.GVA_CONFIG.JWT.SigningKey), + } +} + +// 创建一个token +func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// CreateTokenByOldToken 旧token 换新token 使用归并回源避免并发问题 +func (j *JWT) CreateTokenByOldToken(oldToken string, claims request.CustomClaims) (string, error) { + v, err, _ := global.GVA_Concurrency_Control.Do("JWT:"+oldToken, func() (interface{}, error) { + return j.CreateToken(claims) + }) + return v.(string), err +} + +// 解析 token +func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) { + token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (i interface{}, e 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 token != nil { + if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid { + return claims, nil + } + return nil, TokenInvalid + + } else { + return nil, TokenInvalid + + } + +} \ No newline at end of file diff --git a/web/package.json b/web/package.json index fc754b2a..a61f68f4 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "gin-vue-admin", - "version": "0.1.0", + "version": "2.3.5 ", "private": true, "scripts": { "serve": "node openDocument.js && vue-cli-service serve", diff --git a/web/src/view/layout/aside/historyComponent/history.vue b/web/src/view/layout/aside/historyComponent/history.vue index cd464d94..6dfc2dcc 100644 --- a/web/src/view/layout/aside/historyComponent/history.vue +++ b/web/src/view/layout/aside/historyComponent/history.vue @@ -74,6 +74,9 @@ export default { } }, $route(to, now) { + if (to.name === 'Login') { + return + } this.historys = this.historys.filter(item => !item.meta.closeTab) this.setTab(to) sessionStorage.setItem('historys', JSON.stringify(this.historys)) @@ -84,6 +87,14 @@ export default { } }, created() { + // 全局监听 关闭当前页面函数 + emitter.on('closeThisPage', () => { + this.removeTab(this.name(this.$route)) + }) + // 全局监听 关闭所有页面函数 + emitter.on('closeAllPage', () => { + this.closeAll() + }) emitter.on('mobile', isMobile => { this.isMobile = isMobile }) @@ -109,12 +120,6 @@ export default { } this.setTab(this.$route) }, - mounted() { - // 全局监听 关闭当前页面函数 - emitter.on('closeThisPage', () => { - this.removeTab(this.name(this.$route)) - }) - }, beforeDestroy() { emitter.off('collapse') emitter.off('mobile') diff --git a/web/src/view/layout/index.vue b/web/src/view/layout/index.vue index 8eef7cd8..26684c5f 100644 --- a/web/src/view/layout/index.vue +++ b/web/src/view/layout/index.vue @@ -212,6 +212,7 @@ export default { authorityId: id }) if (res.code === 0) { + emitter.emit('closeAllPage') window.location.reload() } }, -- GitLab