From b68185aed1a86536b01fdfbca6b2cca7bd71a50f Mon Sep 17 00:00:00 2001 From: zhangqian <zhangqian@123.com> Date: 星期六, 23 三月 2024 17:12:18 +0800 Subject: [PATCH] 增加token验证和数据权限过滤 --- middleware/jwt.go | 113 +++++------------- utils/jwt/claims.go | 62 ++++++++++ conf/config.go | 16 +- controllers/order.go | 66 ++++++++++ models/outsourcing_order.go | 9 + conf/config.yaml | 1 utils/jwt/jwt.go | 63 ++++++++++ router/router.go | 2 8 files changed, 238 insertions(+), 94 deletions(-) diff --git a/conf/config.go b/conf/config.go index a8f58ac..3201a3d 100644 --- a/conf/config.go +++ b/conf/config.go @@ -23,14 +23,14 @@ type ( webConf struct { - Host string // 鏈満ip鍦板潃 - Port string // 绔彛鍙� - APPort string // 鏈満浣滀负鐨凣rpc鏈嶅姟绔殑绔彛鍙� - AlHost string // 绠楁硶鏈嶅姟ip鍦板潃 - AlPort string // 绠楁硶鏈嶅姟绔彛鍙� - NodeId string // 涓昏处鎴风敤鎴峰悕 - OssType string // 瀵硅薄瀛樺偍绫诲瀷 - JWTSecret string + Host string // 鏈満ip鍦板潃 + Port string // 绔彛鍙� + APPort string // 鏈満浣滀负鐨凣rpc鏈嶅姟绔殑绔彛鍙� + AlHost string // 绠楁硶鏈嶅姟ip鍦板潃 + AlPort string // 绠楁硶鏈嶅姟绔彛鍙� + NodeId string // 涓昏处鎴风敤鎴峰悕 + OssType string // 瀵硅薄瀛樺偍绫诲瀷 + JWTKey string } nsqConf struct { diff --git a/conf/config.yaml b/conf/config.yaml index 2e0d467..37c133c 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -1,6 +1,7 @@ web: port: 8008 host: 192.168.20.119 + jwtKey: 12345 service: aps: 192.168.20.120:9091 db: diff --git a/controllers/order.go b/controllers/order.go index f627704..c527cf1 100644 --- a/controllers/order.go +++ b/controllers/order.go @@ -13,6 +13,7 @@ "outsourcing/request" "outsourcing/service" "outsourcing/service/outsourcing" + "outsourcing/utils/jwt" ) type OrderController struct{} @@ -30,7 +31,14 @@ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") return } - list, total, err := models.NewOutsourcingOrderSearch().SetPage(params.Page, params.PageSize).SetKeyword(params.Keyword).SetOrder("id desc").Find() + + companyId := jwt.GetCompanyID(c) + if companyId == 0 { + util.ResponseFormat(c, code.InternalError, "鍐呴儴閿欒") + return + } + + list, total, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(companyId).SetPage(params.Page, params.PageSize).SetKeyword(params.Keyword).SetOrder("id desc").Find() if err != nil { util.ResponseFormat(c, code.InternalError, "鏌ヨ閿欒") return @@ -45,7 +53,7 @@ // @Success 200 {object} util.ResponseList{data=request.OutsourcingOrderOverview} "鎴愬姛" // @Router /api-outsourcing/v1/order/overview [get] func (slf *OrderController) OrderOverview(c *gin.Context) { - result, err := models.NewOutsourcingOrderSearch().CountGroupByStatus() + result, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).CountGroupByStatus() if err != nil { util.ResponseFormat(c, code.InternalError, "鏌ヨ閿欒") return @@ -80,6 +88,13 @@ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟缂哄け") return } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetID(params.OutsourcingOrderId).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") + return + } + list, total, err := models.NewOutsourcingOrderProductSearch().SetPage(params.Page, params.PageSize).SetOutsourcingOrderID(params.OutsourcingOrderId).SetOrder("id desc").Find() if err != nil { util.ResponseFormat(c, code.InternalError, "鏌ヨ閿欒") @@ -105,8 +120,15 @@ util.ResponseFormat(c, code.RequestParamError, "鐗╂枡鐢宠涓嶈兘涓虹┖") return } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetNumber(params.ApplyList[0].OutsourcingOrderNumber).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") + return + } + var apply []*models.OutsourcingMaterialApply - err := structx.AssignTo(params.ApplyList, &apply) + err = structx.AssignTo(params.ApplyList, &apply) if err != nil { util.ResponseFormat(c, code.RequestParamError, "鏁版嵁杞崲澶辫触") return @@ -141,6 +163,13 @@ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") return } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetNumber(params.Number).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") + return + } + find, err := models.NewOutsourcingMaterialApplySearch().SetOutsourcingOrderNumber(params.Number).FindNotTotal() if err != nil { util.ResponseFormat(c, code.RequestParamError, "鏌ヨ澶辫触") @@ -162,6 +191,13 @@ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") return } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetNumber(params.OutsourcingOrderNumber).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") + return + } + //闄愬畾鐘舵�佸弬鏁� if params.Status == constvar.OutsourcingOrderStatusCreate || //鍙栨秷纭 params.Status == constvar.OutsourcingOrderStatusWaitProduce || //纭鎺ュ彈 @@ -196,6 +232,12 @@ } if params.OutsourcingOrderID == 0 { util.ResponseFormat(c, code.RequestParamError, "鍙傛暟缂哄け") + return + } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetID(params.OutsourcingOrderID).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") return } @@ -236,6 +278,13 @@ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟缂哄け") return } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetID(params.OutsourcingOrderID).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") + return + } + if len(params.DeliveryList) == 0 { util.ResponseFormat(c, code.RequestParamError, "鍙戣揣鍒楄〃涓嶈兘涓虹┖") return @@ -248,8 +297,8 @@ WaybillNumber: params.WaybillNumber, } - err := models.WithTransaction(func(db *gorm.DB) error { - err := models.NewOutsourcingOrderDeliverySearch().SetOrm(db).Create(delivery) + err = models.WithTransaction(func(db *gorm.DB) error { + err = models.NewOutsourcingOrderDeliverySearch().SetOrm(db).Create(delivery) if err != nil { return err } @@ -285,6 +334,13 @@ util.ResponseFormat(c, code.RequestParamError, "鍙傛暟瑙f瀽澶辫触锛屾暟鎹被鍨嬮敊璇�") return } + + _, err := models.NewOutsourcingOrderSearch().SetEnterpriseID(jwt.GetCompanyID(c)).SetID(params.OutsourcingOrderID).First() + if err != nil { + util.ResponseFormat(c, code.RequestParamError, "璁㈠崟涓嶅瓨鍦�") + return + } + list, err := models.NewOutsourcingOrderDeliveryDetailsSearch(). SetOutsourcingOrderID(params.OutsourcingOrderID). SetPreload(true). diff --git a/middleware/jwt.go b/middleware/jwt.go index f67fc8a..520f651 100644 --- a/middleware/jwt.go +++ b/middleware/jwt.go @@ -1,94 +1,47 @@ package middleware import ( - "errors" - "fmt" - "outsourcing/conf" - "strings" - "time" - - jwt "github.com/dgrijalva/jwt-go" "github.com/gin-gonic/gin" - "outsourcing/extend/util" + "outsourcing/conf" + "outsourcing/pkg/contextx" + "outsourcing/pkg/ecode" + "outsourcing/utils/jwt" + "strings" ) -func validateToken(tokenString string) (util.JSON, error) { - secretKey := []byte(conf.WebConf.JWTSecret) - - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { - // Don't forget to validate the alg is what you expect: - if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { - return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"]) - } - - return secretKey, nil - }) - - if err != nil { - return util.JSON{}, err - } - - if !token.Valid { - return util.JSON{}, errors.New("invalid token") - } - - return token.Claims.(jwt.MapClaims), nil -} - -// JWTMiddleware parses JWT token from cookie and stores data and expires date to the context -// JWT Token can be passed as cookie, or Authorization header -func JWTMiddleware() gin.HandlerFunc { +func JWTAuth() gin.HandlerFunc { return func(c *gin.Context) { - tokenString, err := c.Cookie("token") - // failed to read cookie - if err != nil { - // try reading HTTP Header - authorization := c.Request.Header.Get("Authorization") - if authorization == "" { - c.Next() - return - } - sp := strings.Split(authorization, "Bearer ") - // invalid token - if len(sp) < 1 { - c.Next() - return - } - tokenString = sp[1] - } - - tokenData, err := validateToken(tokenString) - if err != nil { - fmt.Println(err.Error()) - c.Next() + ctx := new(contextx.Context).SetCtx(c) + // 鎴戜滑杩欓噷jwt閴存潈鍙栧ご閮ㄤ俊鎭� Authorization 鐧诲綍鏃跺洖杩斿洖token淇℃伅 杩欓噷鍓嶇闇�瑕佹妸token瀛樺偍鍒癱ookie鎴栬�呮湰鍦發ocalStorage涓� 涓嶈繃闇�瑕佽窡鍚庣鍗忓晢杩囨湡鏃堕棿 鍙互绾﹀畾鍒锋柊浠ょ墝鎴栬�呴噸鏂扮櫥褰� + token := c.Request.Header.Get("Authorization") + if token == "" { + ctx.Fail(ecode.JWTEmpty) + c.Abort() return } - - userParentId := tokenData["parentId"].(string) - if userParentId == conf.WebConf.NodeId { - c.Set("parentId", userParentId) - } else { - c.Next() + slices := strings.Split(token, " ") + if len(slices) == 2 { + token = slices[1] + } + j := jwt.NewOutsideJWT(conf.WebConf.JWTKey) + // parseToken 瑙f瀽token鍖呭惈鐨勪俊鎭� + claims, err := j.ParseToken(token) + if err != nil { + if err == jwt.TokenExpired { + ctx.Fail(ecode.JWTExpire) + c.Abort() + return + } + ctx.Fail(ecode.JWTParseErr) + c.Abort() return } - - c.Set("token_expire", tokenData["exp"]) + if claims.CompanyId == 0 { + ctx.Fail(ecode.JWTExpire) + c.Abort() + return + } + c.Set("claims", claims) c.Next() } -} - -func GenerateToken(data interface{}) (string, error) { - // token is valid for 1 hour - date := time.Now().Add(time.Hour * 12) - - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "user": data, - "exp": date.Unix(), - }) - - secretKey := []byte(conf.WebConf.JWTSecret) - - tokenString, err := token.SignedString(secretKey) - - return tokenString, err } diff --git a/models/outsourcing_order.go b/models/outsourcing_order.go index 8ab108c..11e19cd 100644 --- a/models/outsourcing_order.go +++ b/models/outsourcing_order.go @@ -65,6 +65,11 @@ return slf } +func (slf *OutsourcingOrderSearch) SetEnterpriseID(id uint) *OutsourcingOrderSearch { + slf.EnterpriseID = id + return slf +} + func (slf *OutsourcingOrderSearch) SetIDs(ids []uint) *OutsourcingOrderSearch { slf.IDs = ids return slf @@ -96,6 +101,10 @@ db = db.Where("id = ?", slf.ID) } + if slf.EnterpriseID != 0 { + db = db.Where("enterprise_id = ?", slf.EnterpriseID) + } + if len(slf.IDs) != 0 { db = db.Where("id in ?", slf.IDs) } diff --git a/router/router.go b/router/router.go index a9e935e..1bb46fe 100644 --- a/router/router.go +++ b/router/router.go @@ -22,7 +22,7 @@ urlPrefix := "/api-outsourcing/v1" outsourcingApi := new(controllers.OrderController) - outsourcingGroup := r.Group(urlPrefix + "/order") + outsourcingGroup := r.Group(urlPrefix + "/order").Use(middleware.JWTAuth()) { outsourcingGroup.GET("list", outsourcingApi.OutsourcingOrderList) // 濮斿璁㈠崟鍒楄〃 outsourcingGroup.GET("overview", outsourcingApi.OrderOverview) // 濮斿璁㈠崟缁熻 diff --git a/utils/jwt/claims.go b/utils/jwt/claims.go new file mode 100644 index 0000000..26c5dad --- /dev/null +++ b/utils/jwt/claims.go @@ -0,0 +1,62 @@ +package jwt + +import ( + "github.com/dgrijalva/jwt-go" + "github.com/gin-gonic/gin" + "outsourcing/conf" + "outsourcing/pkg/logx" + "strings" +) + +type OutsideUserClaims struct { + UserId string + Username string + ParentId string + CompanyId uint + CompanyName string + BufferTime int64 + jwt.StandardClaims +} + +func GetClaims(c *gin.Context) (*OutsideUserClaims, error) { + token := c.Request.Header.Get("Authorization") + logx.Infof("GetClaims token:%v", token) + slices := strings.Split(token, " ") + if len(slices) == 2 { + token = slices[1] + } + j := NewOutsideJWT(conf.WebConf.JWTKey) + claims, err := j.ParseToken(token) + if err != nil { + logx.Error("浠嶨in鐨凜ontext涓幏鍙栦粠jwt瑙f瀽淇℃伅澶辫触, 璇锋鏌ヨ姹傚ご鏄惁瀛樺湪x-token涓攃laims鏄惁涓鸿瀹氱粨鏋�") + } + return claims, err +} + +// GetCompanyID 浠嶨in鐨凜ontext涓幏鍙栦粠jwt瑙f瀽鍑烘潵鐨勫叕鍙窱D +func GetCompanyID(c *gin.Context) uint { + if claims, exists := c.Get("claims"); !exists { + if cl, err := GetClaims(c); err != nil { + return 0 + } else { + return cl.CompanyId + } + } else { + waitUse := claims.(*OutsideUserClaims) + return waitUse.CompanyId + } +} + +// GetUserInfo 浠嶨in鐨凜ontext涓幏鍙栦粠jwt瑙f瀽鍑烘潵鐨勭敤鎴蜂俊鎭� +func GetUserInfo(c *gin.Context) *OutsideUserClaims { + if claims, exists := c.Get("claims"); !exists { + if cl, err := GetClaims(c); err != nil { + return nil + } else { + return cl + } + } else { + waitUse := claims.(*OutsideUserClaims) + return waitUse + } +} diff --git a/utils/jwt/jwt.go b/utils/jwt/jwt.go new file mode 100644 index 0000000..8e01128 --- /dev/null +++ b/utils/jwt/jwt.go @@ -0,0 +1,63 @@ +package jwt + +import ( + "errors" + "github.com/dgrijalva/jwt-go" +) + +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:") +) + +type OutSideJWT struct { + SigningKey []byte +} + +func NewOutsideJWT(signKey string) *OutSideJWT { + return &OutSideJWT{ + []byte(signKey), + } +} + +// CreateToken 鍒涘缓涓�涓猼oken +func (j *OutSideJWT) CreateToken(claims OutsideUserClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// ParseToken 瑙f瀽token +func (j *OutSideJWT) ParseToken(tokenString string) (*OutsideUserClaims, error) { + token, err := jwt.ParseWithClaims(tokenString, &OutsideUserClaims{}, 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.(*OutsideUserClaims); ok && token.Valid { + return claims, nil + } + return nil, TokenInvalid + + } else { + return nil, TokenInvalid + } +} -- Gitblit v1.8.0