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