From 55759a33dba731c5eebaafda807f1c8f83fb5a05 Mon Sep 17 00:00:00 2001 From: landaiqing <3517283258@qq.com> Date: Wed, 14 Aug 2024 19:57:37 +0800 Subject: [PATCH] :lock: token encryption --- api/captcha_api/captcha_api.go | 5 +- api/sms_api/sms_api.go | 3 +- api/user_api/user_api.go | 110 ++++++++++++++++-- common/constant/redis_key.go | 9 ++ config/conf_encrypt.go | 8 ++ config/config.go | 13 ++- go.mod | 1 + go.sum | 5 + middleware/jwt.go | 2 +- model/sca_auth_permission.go | 9 ++ model/sca_auth_role.go | 9 ++ router/modules/user_router.go | 8 +- service/permission_service/permission.go | 3 + .../permission_service/permission_service.go | 15 +++ .../role_permission.go | 3 + .../role_permission_service.go | 17 +++ service/role_service/role_service.go | 12 +- service/service.go | 10 +- utils/jwt.go | 38 +++++- 19 files changed, 241 insertions(+), 39 deletions(-) create mode 100644 common/constant/redis_key.go create mode 100644 config/conf_encrypt.go create mode 100644 service/permission_service/permission.go create mode 100644 service/permission_service/permission_service.go create mode 100644 service/role_permission_service/role_permission.go create mode 100644 service/role_permission_service/role_permission_service.go diff --git a/api/captcha_api/captcha_api.go b/api/captcha_api/captcha_api.go index 2a2a0ee..705d0e2 100644 --- a/api/captcha_api/captcha_api.go +++ b/api/captcha_api/captcha_api.go @@ -11,6 +11,7 @@ import ( "github.com/wenlng/go-captcha/v2/slide" "log" "schisandra-cloud-album/api/captcha_api/dto" + "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" @@ -44,7 +45,7 @@ func (CaptchaAPI) GenerateRotateCaptcha(c *gin.Context) { return } key := helper.StringToMD5(string(dotsByte)) - err = redis.Set("user:login:client:"+key, dotsByte, time.Minute).Err() + err = redis.Set(constant.UserLoginCaptchaRedisKey+key, dotsByte, time.Minute).Err() if err != nil { result.FailWithNull(c) return @@ -74,7 +75,7 @@ func (CaptchaAPI) CheckRotateData(c *gin.Context) { result.FailWithNull(c) return } - cacheDataByte, err := redis.Get("user:login:client:" + key).Bytes() + cacheDataByte, err := redis.Get(constant.UserLoginCaptchaRedisKey + key).Bytes() if len(cacheDataByte) == 0 || err != nil { result.FailWithCodeAndMessage(1011, ginI18n.MustGetMessage(c, "CaptchaExpired"), c) return diff --git a/api/sms_api/sms_api.go b/api/sms_api/sms_api.go index 300333a..8ce8817 100644 --- a/api/sms_api/sms_api.go +++ b/api/sms_api/sms_api.go @@ -7,6 +7,7 @@ import ( "github.com/pkg6/go-sms/gateways" "github.com/pkg6/go-sms/gateways/aliyun" "github.com/pkg6/go-sms/gateways/smsbao" + "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" "schisandra-cloud-album/global" @@ -102,7 +103,7 @@ func (SmsAPI) SendMessageTest(c *gin.Context) { return } code := utils.GenValidateCode(6) - err := redis.Set("user:login:sms:"+phone, code, time.Minute).Err() + err := redis.Set(constant.UserLoginSmsRedisKey+phone, code, time.Minute).Err() if err != nil { global.LOG.Error(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaSendFailed"), c) diff --git a/api/user_api/user_api.go b/api/user_api/user_api.go index 8355a37..c6cf33d 100644 --- a/api/user_api/user_api.go +++ b/api/user_api/user_api.go @@ -1,11 +1,14 @@ package user_api import ( + "encoding/json" ginI18n "github.com/gin-contrib/i18n" "github.com/gin-gonic/gin" + "github.com/wumansgy/goEncrypt/aes" "github.com/yitter/idgenerator-go/idgen" "reflect" "schisandra-cloud-album/api/user_api/dto" + "schisandra-cloud-album/common/constant" "schisandra-cloud-album/common/enum" "schisandra-cloud-album/common/redis" "schisandra-cloud-album/common/result" @@ -19,6 +22,9 @@ import ( var userService = service.Service.UserService var userRoleService = service.Service.UserRoleService +var rolePermissionService = service.Service.RolePermissionService +var permissionServiceService = service.Service.PermissionService +var roleService = service.Service.RoleService // GetUserList // @Summary 获取所有用户列表 @@ -187,7 +193,7 @@ func (UserAPI) PhoneLogin(c *gin.Context) { user := userService.QueryUserByPhone(phone) if reflect.DeepEqual(user, model.ScaAuthUser{}) { // 未注册 - code := redis.Get("user:login:sms:" + phone) + code := redis.Get(constant.UserLoginSmsRedisKey + phone) if code == nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c) return @@ -217,6 +223,36 @@ func (UserAPI) PhoneLogin(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) return } + permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids) + permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + serializedPermissions, err := json.Marshal(permissions) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + wrong := redis.Set(constant.UserAuthPermissionRedisKey+*addUser.UID, serializedPermissions, 0).Err() + if wrong != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + roleList, err := roleService.GetRoleListByIds(ids) + if err != nil { + return + } + serializedRoleList, err := json.Marshal(roleList) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + er := redis.Set(constant.UserAuthRoleRedisKey+*addUser.UID, serializedRoleList, 0).Err() + if er != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } accessToken, refreshToken, expiresAt := utils.GenerateAccessTokenAndRefreshToken(utils.JWTPayload{UserID: addUser.UID, RoleID: ids}) data := dto.ResponseData{ @@ -225,7 +261,7 @@ func (UserAPI) PhoneLogin(c *gin.Context) { ExpiresAt: expiresAt, UID: addUser.UID, } - fail := redis.Set("user:login:token:"+*addUser.UID, data, time.Hour*24*30).Err() + fail := redis.Set(constant.UserLoginTokenRedisKey+*addUser.UID, data, time.Hour*24*7).Err() if fail != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) return @@ -234,7 +270,7 @@ func (UserAPI) PhoneLogin(c *gin.Context) { return } } else { - code := redis.Get("user:login:sms:" + phone) + code := redis.Get(constant.UserLoginSmsRedisKey + phone) if code == nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "CaptchaExpired"), c) return @@ -248,6 +284,36 @@ func (UserAPI) PhoneLogin(c *gin.Context) { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) return } + permissionIds := rolePermissionService.QueryPermissionIdsByRoleId(ids) + permissions, err := permissionServiceService.GetPermissionsByIds(permissionIds) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + serializedPermissions, err := json.Marshal(permissions) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + wrong := redis.Set(constant.UserAuthPermissionRedisKey+*user.UID, serializedPermissions, 0).Err() + if wrong != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + roleList, err := roleService.GetRoleListByIds(ids) + if err != nil { + return + } + serializedRoleList, err := json.Marshal(roleList) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } + er := redis.Set(constant.UserAuthRoleRedisKey+*user.UID, serializedRoleList, 0).Err() + if er != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) + return + } accessToken, refreshToken, expiresAt := utils.GenerateAccessTokenAndRefreshToken(utils.JWTPayload{UserID: user.UID, RoleID: ids}) data := dto.ResponseData{ @@ -256,7 +322,7 @@ func (UserAPI) PhoneLogin(c *gin.Context) { ExpiresAt: expiresAt, UID: user.UID, } - fail := redis.Set("user:login:token:"+*user.UID, data, time.Hour*24*30).Err() + fail := redis.Set(constant.UserLoginTokenRedisKey+*user.UID, data, time.Hour*24*7).Err() if fail != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginFailed"), c) return @@ -277,26 +343,46 @@ func (UserAPI) PhoneLogin(c *gin.Context) { // @Success 200 {string} json // @Router /api/auth/token/refresh [post] func (UserAPI) RefreshHandler(c *gin.Context) { - refreshToken := c.Query("refresh_token") - if refreshToken == "" { - result.FailWithMessage("refresh_token不能为空!", c) + request := dto.RefreshTokenRequest{} + err := c.ShouldBindJSON(&request) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) return } - parseRefreshToken, isUpd, err := utils.ParseToken(refreshToken) + refreshToken := request.RefreshToken + if refreshToken == "" { + result.FailWithMessage(ginI18n.MustGetMessage(c, "ParamsError"), c) + return + } + plaintext, err := aes.AesCtrDecryptByHex(refreshToken, []byte(global.CONFIG.Encrypt.Key), []byte(global.CONFIG.Encrypt.IV)) + if err != nil { + global.LOG.Error(err) + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) + return + } + parseRefreshToken, isUpd, err := utils.ParseToken(string(plaintext)) if err != nil { global.LOG.Errorln(err) result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) return } if isUpd { - accessTokenString, refreshTokenString, expiresAt := utils.GenerateAccessTokenAndRefreshToken(utils.JWTPayload{UserID: parseRefreshToken.UserID, RoleID: parseRefreshToken.RoleID}) + accessTokenString, err := utils.GenerateAccessToken(utils.JWTPayload{UserID: parseRefreshToken.UserID, RoleID: parseRefreshToken.RoleID}) + if err != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) + return + } + wrong := redis.Get(constant.UserLoginTokenRedisKey + *parseRefreshToken.UserID).Err() + if wrong != nil { + result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) + return + } data := dto.ResponseData{ AccessToken: accessTokenString, - RefreshToken: refreshTokenString, - ExpiresAt: expiresAt, + RefreshToken: refreshToken, UID: parseRefreshToken.UserID, } - fail := redis.Set("user:login:token:"+*parseRefreshToken.UserID, data, time.Hour*24*30).Err() + fail := redis.Set("user:login:token:"+*parseRefreshToken.UserID, data, time.Hour*24*7).Err() if fail != nil { result.FailWithMessage(ginI18n.MustGetMessage(c, "LoginExpired"), c) return diff --git a/common/constant/redis_key.go b/common/constant/redis_key.go new file mode 100644 index 0000000..2a7c5a5 --- /dev/null +++ b/common/constant/redis_key.go @@ -0,0 +1,9 @@ +package constant + +const ( + UserLoginSmsRedisKey = "user:login:sms:" + UserLoginTokenRedisKey = "user:login:token:" + UserLoginCaptchaRedisKey = "user:login:captcha:" + UserAuthRoleRedisKey = "user:auth:role:" + UserAuthPermissionRedisKey = "user:auth:permission:" +) diff --git a/config/conf_encrypt.go b/config/conf_encrypt.go new file mode 100644 index 0000000..1067d43 --- /dev/null +++ b/config/conf_encrypt.go @@ -0,0 +1,8 @@ +package config + +type Encrypt struct { + Key string `yaml:"key"` + IV string `yaml:"iv"` + PublicKey string `yaml:"public-key"` + PrivateKey string `yaml:"private-key"` +} diff --git a/config/config.go b/config/config.go index 46728e3..69aaa5a 100644 --- a/config/config.go +++ b/config/config.go @@ -1,10 +1,11 @@ package config type Config struct { - MySQL MySQL `yaml:"mysql"` - Logger Logger `yaml:"logger"` - System System `yaml:"system"` - Redis Redis `yaml:"redis"` - SMS SMS `yaml:"sms"` - JWT JWT `yaml:"jwt"` + MySQL MySQL `yaml:"mysql"` + Logger Logger `yaml:"logger"` + System System `yaml:"system"` + Redis Redis `yaml:"redis"` + SMS SMS `yaml:"sms"` + JWT JWT `yaml:"jwt"` + Encrypt Encrypt `yaml:"encrypt"` } diff --git a/go.mod b/go.mod index 0183e63..2e4a745 100644 --- a/go.mod +++ b/go.mod @@ -61,6 +61,7 @@ require ( github.com/pkg6/go-sms v0.1.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect + github.com/wumansgy/goEncrypt v1.1.0 // indirect github.com/yitter/idgenerator-go v1.3.3 // indirect golang.org/x/arch v0.8.0 // indirect golang.org/x/image v0.18.0 // indirect diff --git a/go.sum b/go.sum index 2dcd71b..eeb855c 100644 --- a/go.sum +++ b/go.sum @@ -127,12 +127,14 @@ github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0 github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -155,6 +157,8 @@ github.com/wenlng/go-captcha-assets v1.0.1 h1:AdjRFMKmadPRWRTv0XEYfjDvcaayZ2yExI github.com/wenlng/go-captcha-assets v1.0.1/go.mod h1:yQqc7rRbxgLCg+tWtVp+7Y317D1wIZDan/yIwt8wSac= github.com/wenlng/go-captcha/v2 v2.0.0 h1:7Z4Zy09SIHgvj9e8ZxP4VhYOwg7IHt8kGlVrE5jP5Z8= github.com/wenlng/go-captcha/v2 v2.0.0/go.mod h1:5hac1em3uXoyC5ipZ0xFv9umNM/waQvYAQdr0cx/h34= +github.com/wumansgy/goEncrypt v1.1.0 h1:Krr2FJL4GEsMTBvLfsnoTmgWb7rkGnL4siJ9K2cxMs0= +github.com/wumansgy/goEncrypt v1.1.0/go.mod h1:dWgF7mi5Ujmt8V5EoyRqjH6XtZ8wmNQyT4u2uvH8Pyg= github.com/yitter/idgenerator-go v1.3.3 h1:i6rzmpbCL0vlmr/tuW5+lSQzNuDG9vYBjIYRvnRcHE8= github.com/yitter/idgenerator-go v1.3.3/go.mod h1:VVjbqFjGUsIkaXVkXEdmx1LiXUL3K1NvyxWPJBPbBpE= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -184,6 +188,7 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/middleware/jwt.go b/middleware/jwt.go index f006e44..052ab35 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -21,7 +21,7 @@ func JWTAuthMiddleware() gin.HandlerFunc { headerPrefix := global.CONFIG.JWT.HeaderPrefix accessToken := strings.TrimPrefix(authHeader, headerPrefix+" ") - if accessToken == "undefined" || accessToken == "" { + if accessToken == "" { c.Abort() result.FailWithMessage(ginI18n.MustGetMessage(c, "AuthVerifyFailed"), c) return diff --git a/model/sca_auth_permission.go b/model/sca_auth_permission.go index c5789cb..513b401 100644 --- a/model/sca_auth_permission.go +++ b/model/sca_auth_permission.go @@ -1,6 +1,7 @@ package model import ( + "encoding/json" "time" ) @@ -29,3 +30,11 @@ type ScaAuthPermission struct { func (*ScaAuthPermission) TableName() string { return TableNameScaAuthPermission } + +func (permission *ScaAuthPermission) MarshalBinary() ([]byte, error) { + return json.Marshal(permission) +} + +func (permission *ScaAuthPermission) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, permission) +} diff --git a/model/sca_auth_role.go b/model/sca_auth_role.go index be08912..3c6c51e 100644 --- a/model/sca_auth_role.go +++ b/model/sca_auth_role.go @@ -1,6 +1,7 @@ package model import ( + "encoding/json" "time" ) @@ -22,3 +23,11 @@ type ScaAuthRole struct { func (*ScaAuthRole) TableName() string { return TableNameScaAuthRole } + +func (role *ScaAuthRole) MarshalBinary() ([]byte, error) { + return json.Marshal(role) +} + +func (role *ScaAuthRole) UnmarshalBinary(data []byte) error { + return json.Unmarshal(data, role) +} diff --git a/router/modules/user_router.go b/router/modules/user_router.go index fded1c8..2216383 100644 --- a/router/modules/user_router.go +++ b/router/modules/user_router.go @@ -17,9 +17,13 @@ func UserRouter(router *gin.RouterGroup) { } authGroup := router.Group("auth").Use(middleware.JWTAuthMiddleware()) { - authGroup.GET("/user/List", userApi.GetUserList) + authGroup.GET("/user/list", userApi.GetUserList) authGroup.GET("/user/query_by_uuid", userApi.QueryUserByUuid) - authGroup.POST("/token/refresh", userApi.RefreshHandler) + + } + tokenGroup := router.Group("token") + { + tokenGroup.POST("/refresh", userApi.RefreshHandler) } } diff --git a/service/permission_service/permission.go b/service/permission_service/permission.go new file mode 100644 index 0000000..73efc92 --- /dev/null +++ b/service/permission_service/permission.go @@ -0,0 +1,3 @@ +package permission_service + +type PermissionService struct{} diff --git a/service/permission_service/permission_service.go b/service/permission_service/permission_service.go new file mode 100644 index 0000000..07809bc --- /dev/null +++ b/service/permission_service/permission_service.go @@ -0,0 +1,15 @@ +package permission_service + +import ( + "schisandra-cloud-album/global" + "schisandra-cloud-album/model" +) + +// GetPermissionsByIds 通过权限ID列表获取权限列表 +func (PermissionService) GetPermissionsByIds(ids []int64) ([]model.ScaAuthPermission, error) { + var permissions []model.ScaAuthPermission + if err := global.DB.Where("id IN ?", ids).Find(&permissions).Error; err != nil { + return nil, err + } + return permissions, nil +} diff --git a/service/role_permission_service/role_permission.go b/service/role_permission_service/role_permission.go new file mode 100644 index 0000000..697fe57 --- /dev/null +++ b/service/role_permission_service/role_permission.go @@ -0,0 +1,3 @@ +package role_permission_service + +type RolePermissionService struct{} diff --git a/service/role_permission_service/role_permission_service.go b/service/role_permission_service/role_permission_service.go new file mode 100644 index 0000000..e99d277 --- /dev/null +++ b/service/role_permission_service/role_permission_service.go @@ -0,0 +1,17 @@ +package role_permission_service + +import ( + "schisandra-cloud-album/global" + "schisandra-cloud-album/model" +) + +// QueryPermissionIdsByRoleId 通过角色ID列表查询权限ID列表 +func (RolePermissionService) QueryPermissionIdsByRoleId(roleIds []*int64) []int64 { + var permissionIds []int64 + rolePermission := model.ScaAuthRolePermission{} + if err := global.DB.Model(&rolePermission).Where("role_id IN ?", roleIds).Pluck("permission_id", &permissionIds).Error; err != nil { + global.LOG.Error(err) + return nil + } + return permissionIds +} diff --git a/service/role_service/role_service.go b/service/role_service/role_service.go index 2b77984..5c041c9 100644 --- a/service/role_service/role_service.go +++ b/service/role_service/role_service.go @@ -5,11 +5,11 @@ import ( "schisandra-cloud-album/model" ) -// GetRoleById : 通过Id获取角色信息 -func (RoleService) GetRoleById(id int64) (model.ScaAuthRole, error) { - var role model.ScaAuthRole - if err := global.DB.Where("id = ? and deleted = 0", id).First(&role).Error; err != nil { - return model.ScaAuthRole{}, err +// GetRoleListByIds : 通过Id列表获取角色信息列表 +func (RoleService) GetRoleListByIds(id []*int64) ([]model.ScaAuthRole, error) { + var roles []model.ScaAuthRole + if err := global.DB.Where("id IN ?", id).Find(&roles).Error; err != nil { + return nil, err } - return role, nil + return roles, nil } diff --git a/service/service.go b/service/service.go index 1aef04e..cd285dd 100644 --- a/service/service.go +++ b/service/service.go @@ -1,6 +1,8 @@ package service import ( + "schisandra-cloud-album/service/permission_service" + "schisandra-cloud-album/service/role_permission_service" "schisandra-cloud-album/service/role_service" "schisandra-cloud-album/service/user_role_service" "schisandra-cloud-album/service/user_service" @@ -8,9 +10,11 @@ import ( // Services 统一导出的service type Services struct { - UserService user_service.UserService - RoleService role_service.RoleService - UserRoleService user_role_service.UserRoleService + UserService user_service.UserService + RoleService role_service.RoleService + UserRoleService user_role_service.UserRoleService + RolePermissionService role_permission_service.RolePermissionService + PermissionService permission_service.PermissionService } // Service new函数实例化,实例化完成后会返回结构体地指针类型 diff --git a/utils/jwt.go b/utils/jwt.go index 44b3be2..cc951f6 100644 --- a/utils/jwt.go +++ b/utils/jwt.go @@ -1,7 +1,9 @@ package utils import ( + "fmt" "github.com/golang-jwt/jwt/v5" + "github.com/wumansgy/goEncrypt/aes" "schisandra-cloud-album/global" "time" ) @@ -18,19 +20,28 @@ type JWTClaims struct { var MySecret []byte -// GenerateToken generates a JWT token with the given payload -func GenerateToken(payload JWTPayload) (string, error) { +// GenerateAccessToken generates a JWT token with the given payload +func GenerateAccessToken(payload JWTPayload) (string, error) { MySecret = []byte(global.CONFIG.JWT.Secret) claims := JWTClaims{ JWTPayload: payload, RegisteredClaims: jwt.RegisteredClaims{ - ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), + ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 2)), IssuedAt: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()), }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) - return token.SignedString(MySecret) + signedString, err := token.SignedString(MySecret) + if err != nil { + return "", err + } + accessToken, err := aes.AesCtrEncryptHex([]byte(signedString), []byte(global.CONFIG.Encrypt.Key), []byte(global.CONFIG.Encrypt.IV)) + if err != nil { + fmt.Println(err) + return "", err + } + return accessToken, nil } // GenerateAccessTokenAndRefreshToken generates a JWT token with the given payload, and returns the accessToken and refreshToken @@ -67,13 +78,28 @@ func GenerateAccessTokenAndRefreshToken(payload JWTPayload) (string, string, int global.LOG.Error(err) return "", "", 0 } - return accessTokenString, refreshTokenString, refreshClaims.ExpiresAt.Time.Unix() + accessTokenEncrypted, err := aes.AesCtrEncryptHex([]byte(accessTokenString), []byte(global.CONFIG.Encrypt.Key), []byte(global.CONFIG.Encrypt.IV)) + if err != nil { + fmt.Println(err) + return "", "", 0 + } + refreshTokenEncrypted, err := aes.AesCtrEncryptHex([]byte(refreshTokenString), []byte(global.CONFIG.Encrypt.Key), []byte(global.CONFIG.Encrypt.IV)) + if err != nil { + fmt.Println(err) + return "", "", 0 + } + return accessTokenEncrypted, refreshTokenEncrypted, refreshClaims.ExpiresAt.Time.Unix() } // ParseToken parses a JWT token and returns the payload func ParseToken(tokenString string) (*JWTPayload, bool, error) { MySecret = []byte(global.CONFIG.JWT.Secret) - token, err := jwt.ParseWithClaims(tokenString, &JWTClaims{}, func(token *jwt.Token) (interface{}, error) { + plaintext, err := aes.AesCtrDecryptByHex(tokenString, []byte(global.CONFIG.Encrypt.Key), []byte(global.CONFIG.Encrypt.IV)) + if err != nil { + global.LOG.Error(err) + return nil, false, err + } + token, err := jwt.ParseWithClaims(string(plaintext), &JWTClaims{}, func(token *jwt.Token) (interface{}, error) { return MySecret, nil }) if err != nil {