From 3b474a056ea35196ce5d2a5f297eafa11295a95d Mon Sep 17 00:00:00 2001 From: liujiandao <274878379@qq.com> Date: 星期三, 22 十一月 2023 14:23:13 +0800 Subject: [PATCH] 添加登录功能 --- request/jwt.go | 20 + go.mod | 3 pkg/ecode/code.go | 21 + pkg/contextx/contextx.go | 97 ++++++++ constvar/const.go | 9 pkg/logx/json.go | 91 +++++++ pkg/logx/service.go | 49 ++++ go.sum | 13 middleware/utils.go | 60 +++++ pkg/logx/console.go | 89 +++++++ middleware/jwt.go | 39 +++ pkg/logx/index.go | 158 +++++++++++++ initialize/router.go | 8 pkg/ecode/msg.go | 24 ++ 14 files changed, 669 insertions(+), 12 deletions(-) diff --git a/constvar/const.go b/constvar/const.go new file mode 100644 index 0000000..384dbfa --- /dev/null +++ b/constvar/const.go @@ -0,0 +1,9 @@ +package constvar + +type UserType int + +const ( + UserTypeSuper UserType = iota + 1 // 瓒呯骇绠$悊鍛� + UserTypePrimary // 涓昏处鎴� + UserTypeSub // 瀛愯处鎴� +) diff --git a/go.mod b/go.mod index ba23ae5..879a5a1 100644 --- a/go.mod +++ b/go.mod @@ -3,11 +3,13 @@ go 1.18 require ( + github.com/dgrijalva/jwt-go v3.2.0+incompatible github.com/fsnotify/fsnotify v1.6.0 github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6 github.com/gin-gonic/gin v1.9.1 github.com/glebarez/sqlite v1.8.0 github.com/go-sql-driver/mysql v1.7.1 + github.com/golang-jwt/jwt/v4 v4.5.0 github.com/h2non/filetype v1.1.3 github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible github.com/redis/go-redis/v9 v9.0.5 @@ -23,6 +25,7 @@ golang.org/x/sync v0.3.0 google.golang.org/grpc v1.55.0 google.golang.org/protobuf v1.30.0 + gopkg.in/natefinch/lumberjack.v2 v2.2.1 gorm.io/driver/mysql v1.5.1 gorm.io/driver/postgres v1.5.2 gorm.io/driver/sqlserver v1.5.1 diff --git a/go.sum b/go.sum index 5995390..92c4d46 100644 --- a/go.sum +++ b/go.sum @@ -45,7 +45,6 @@ github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -73,6 +72,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko= @@ -140,10 +141,10 @@ github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= @@ -226,16 +227,10 @@ github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= -github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= -github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU= github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8= github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs= @@ -769,6 +764,8 @@ gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= +gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/initialize/router.go b/initialize/router.go index 4b390f7..584dbf3 100644 --- a/initialize/router.go +++ b/initialize/router.go @@ -2,6 +2,7 @@ import ( "net/http" + "srm/middleware" "srm/router/purchase" "github.com/gin-gonic/gin" @@ -25,16 +26,15 @@ global.GVA_LOG.Info("register swagger handler") // 鏂逛究缁熶竴娣诲姞璺敱缁勫墠缂� 澶氭湇鍔″櫒涓婄嚎浣跨敤 - PublicGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix) + PrivateGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix) { // 鍋ュ悍鐩戞祴 - PublicGroup.GET("/health", func(c *gin.Context) { + PrivateGroup.GET("/health", func(c *gin.Context) { c.JSON(http.StatusOK, "ok") }) //systemRouter.InitInitRouter(PublicGroup) // 鑷姩鍒濆鍖栫浉鍏� } - - PrivateGroup := Router.Group(global.GVA_CONFIG.System.RouterPrefix) + PrivateGroup.Use(middleware.JWTAuth()) { systemRouter.InitSystemRouter(PrivateGroup) // system鐩稿叧璺敱 //exampleRouter.InitFileUploadAndDownloadRouter(PrivateGroup) // 鏂囦欢涓婁紶涓嬭浇鍔熻兘璺敱 diff --git a/middleware/jwt.go b/middleware/jwt.go new file mode 100644 index 0000000..42ce6e0 --- /dev/null +++ b/middleware/jwt.go @@ -0,0 +1,39 @@ +package middleware + +import ( + "github.com/gin-gonic/gin" + "srm/pkg/contextx" + "srm/pkg/ecode" + "strings" +) + +func JWTAuth() gin.HandlerFunc { + return func(c *gin.Context) { + 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 + } + slices := strings.Split(token, " ") + if len(slices) == 2 { + token = slices[1] + } + j := NewJWT() + // parseToken 瑙f瀽token鍖呭惈鐨勪俊鎭� + claims, err := j.ParseToken(token) + if err != nil { + if err == TokenExpired { + c.Next() + return + } + c.Next() + return + } + + c.Set("claims", claims) + c.Next() + } +} diff --git a/middleware/utils.go b/middleware/utils.go new file mode 100644 index 0000000..190a77a --- /dev/null +++ b/middleware/utils.go @@ -0,0 +1,60 @@ +package middleware + +import ( + "errors" + "github.com/golang-jwt/jwt/v4" + "srm/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("327a9457-899a-481e-8b30-58cc97e5b808"), + } +} + +// CreateToken 鍒涘缓涓�涓猼oken +func (j *JWT) CreateToken(claims request.CustomClaims) (string, error) { + token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) + return token.SignedString(j.SigningKey) +} + +// ParseToken 瑙f瀽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 + } +} diff --git a/pkg/contextx/contextx.go b/pkg/contextx/contextx.go new file mode 100644 index 0000000..958df06 --- /dev/null +++ b/pkg/contextx/contextx.go @@ -0,0 +1,97 @@ +package contextx + +import ( + "github.com/gin-gonic/gin" + "net/http" + "srm/pkg/ecode" + "srm/pkg/logx" +) + +type ( + Context struct { + ctx *gin.Context + paramsMap map[string]interface{} + } + + Response struct { + Code int `json:"code"` + Data interface{} `json:"data"` + Msg string `json:"msg"` + } +) + +func NewContext(ctx *gin.Context, params interface{}) (r *Context, isAllow bool) { + r = &Context{ + ctx: ctx, + } + if r.ctx.Request.Method == "OPTIONS" { + r.ctx.String(http.StatusOK, "") + return + } + + defer func() { + query := r.ctx.Request.URL.RawQuery + if query != "" { + query = "?" + query + } + urlPath := r.ctx.Request.URL.Path + logx.Infof("%s | %s %s | uid: %s | %+v", ctx.ClientIP(), r.ctx.Request.Method, urlPath+query, r.GetUserId(), params) + }() + + // validate params + if params != nil { + if err := r.ctx.ShouldBind(params); err != nil { + r.Fail(ecode.ParamsErr) + return + } + } + isAllow = true + return +} + +func (slf *Context) GetRequestPath() (r string) { + r = slf.ctx.Request.URL.Path + return +} + +func (slf *Context) GetUserId() (r string) { + v := slf.paramsMap["userId"] + switch v.(type) { + case string: + r = v.(string) + } + return +} + +func (slf *Context) Result(code int, data interface{}, msg string) { + slf.ctx.JSON(http.StatusOK, Response{ + Code: code, + Data: data, + Msg: msg, + }) +} + +func (slf *Context) Ok() { + slf.Result(ecode.OK, map[string]interface{}{}, "") +} + +func (slf *Context) OkWithDetailed(data interface{}) { + slf.Result(ecode.OK, data, "") +} + +func (slf *Context) Fail(errCode int) { + slf.Result(errCode, map[string]interface{}{}, ecode.GetMsg(errCode)) +} + +func (slf *Context) FailWithDetailed(errCode int, data interface{}) { + slf.Result(errCode, data, ecode.GetMsg(errCode)) +} + +func (slf *Context) GetCtx() *gin.Context { + return slf.ctx +} + +func (slf *Context) SetCtx(c *gin.Context) *Context { + slf.ctx = c + return slf +} diff --git a/pkg/ecode/code.go b/pkg/ecode/code.go new file mode 100644 index 0000000..aa74251 --- /dev/null +++ b/pkg/ecode/code.go @@ -0,0 +1,21 @@ +package ecode + +const ( + OK = 200 + + UnknownErr = 2001 // 鏈煡閿欒 + DBErr = 2002 // db閿欒 + RedisErr = 2003 // redis閿欒 + ParamsErr = 2004 // 璇锋眰鍙傛暟閿欒 + UserNotExist = 2005 // 鐢ㄦ埛涓嶅瓨鍦� + PasswordErr = 2006 // 瀵嗙爜閿欒 + UserForbidden = 2007 // 鐢ㄦ埛琚鐢� + CaptchaGenerateFailed = 2008 // 楠岃瘉鐮佺敓鎴愬け璐� + CaptchaErr = 2009 // 楠岃瘉鐮侀敊璇� + CreateTokenErr = 2010 // 鍒涘缓token澶辫触 + JWTInBlackList = 2011 // JWT鍦ㄧ櫧鍚嶅崟 + JWTDisabled = 2012 // JWT澶辨晥 + JWTEmpty = 2013 // JWT涓虹┖ + JWTExpire = 2014 // JWT杩囨湡 + JWTParseErr = 2015 // JWT瑙f瀽澶辫触 +) diff --git a/pkg/ecode/msg.go b/pkg/ecode/msg.go new file mode 100644 index 0000000..9b5ebe5 --- /dev/null +++ b/pkg/ecode/msg.go @@ -0,0 +1,24 @@ +package ecode + +var MsgFlags = map[int]string{ + UnknownErr: "鏈煡閿欒", + DBErr: "db閿欒", + RedisErr: "redis閿欒", + ParamsErr: "璇锋眰鍙傛暟閿欒", + UserNotExist: "鐢ㄦ埛涓嶅瓨鍦�", + PasswordErr: "瀵嗙爜閿欒", + UserForbidden: "鐢ㄦ埛琚鐢�", + CaptchaGenerateFailed: "楠岃瘉鐮佺敓鎴愬け璐�", + CaptchaErr: "楠岃瘉鐮侀敊璇�", + CreateTokenErr: "鍒涘缓token澶辫触", + JWTInBlackList: "JWT鍦ㄧ櫧鍚嶅崟", + JWTDisabled: "JWT澶辨晥", + JWTEmpty: "JWT涓虹┖", + JWTExpire: "JWT杩囨湡", + JWTParseErr: "JWT瑙f瀽澶辫触", +} + +func GetMsg(errCode int) (errMsg string) { + errMsg, _ = MsgFlags[errCode] + return +} diff --git a/pkg/logx/console.go b/pkg/logx/console.go new file mode 100644 index 0000000..fe1d18a --- /dev/null +++ b/pkg/logx/console.go @@ -0,0 +1,89 @@ +package logx + +import ( + "fmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "time" +) + +type ConsoleLog struct { + val string +} + +func NewConsoleLog() Encoder { + return new(ConsoleLog) +} + +// Config 鑷畾涔夐厤缃�. +func (slf *ConsoleLog) Config() zapcore.Encoder { + var ( + cfg = zap.NewProductionEncoderConfig() + ) + + // 鏃堕棿鏍煎紡鑷畾涔� + cfg.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString("[" + t.Format("2006-01-02 15:04:05") + "]") + } + // 鎵撳嵃璺緞鑷畾涔� + cfg.EncodeCaller = func(caller zapcore.EntryCaller, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString("[" + getFilePath(caller) + "]") + } + // 绾у埆鏄剧ず鑷畾涔� + cfg.EncodeLevel = func(level zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString("[" + level.String() + "]") + } + return zapcore.NewConsoleEncoder(cfg) +} + +// WithKey 娣诲姞鍗曚釜閿�. +func (slf *ConsoleLog) WithKey(key string) Encoder { + slf.val = slf.val + "[" + key + "] " + return slf +} + +// WithField 娣诲姞瀛楁. +func (slf *ConsoleLog) WithField(key, val string) Encoder { + slf.val = slf.val + fmt.Sprintf("[%s:%s] ", key, val) + return slf +} + +func (slf *ConsoleLog) Debug(msg string) { + _logger.Debug(slf.val + msg) +} + +func (slf *ConsoleLog) Debugf(format string, v ...interface{}) { + _logger.Debug(fmt.Sprintf(slf.val+format, v...)) +} + +func (slf *ConsoleLog) Info(msg string) { + _logger.Info(slf.val + msg) +} + +func (slf *ConsoleLog) Infof(format string, v ...interface{}) { + _logger.Info(fmt.Sprintf(slf.val+format, v...)) +} + +func (slf *ConsoleLog) Warn(msg string) { + _logger.Warn(slf.val + msg) +} + +func (slf *ConsoleLog) Warnf(format string, v ...interface{}) { + _logger.Warn(fmt.Sprintf(slf.val+format, v...)) +} + +func (slf *ConsoleLog) Error(msg string) { + _logger.Error(slf.val + msg) +} + +func (slf *ConsoleLog) Errorf(format string, v ...interface{}) { + _logger.Error(fmt.Sprintf(slf.val+format, v...)) +} + +func (slf *ConsoleLog) Fatal(msg string) { + _logger.Fatal(slf.val + msg) +} + +func (slf *ConsoleLog) Fatalf(format string, v ...interface{}) { + _logger.Fatal(fmt.Sprintf(slf.val+format, v...)) +} diff --git a/pkg/logx/index.go b/pkg/logx/index.go new file mode 100644 index 0000000..42e4213 --- /dev/null +++ b/pkg/logx/index.go @@ -0,0 +1,158 @@ +package logx + +import ( + "go.uber.org/zap" + "go.uber.org/zap/buffer" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" + "os" + "path" + "strings" +) + +type ( + Conf struct { + Path string // 鏃ュ織璺緞 + Encoder string // 缂栫爜鍣ㄩ�夋嫨 + } + logItem struct { + FileName string + Level zap.LevelEnablerFunc + } + Encoder interface { + Config() zapcore.Encoder + WithKey(key string) Encoder + WithField(key, val string) Encoder + Debug(msg string) + Debugf(format string, v ...interface{}) + Info(msg string) + Infof(format string, v ...interface{}) + Warn(msg string) + Warnf(format string, v ...interface{}) + Error(msg string) + Errorf(format string, v ...interface{}) + Fatal(msg string) + Fatalf(format string, v ...interface{}) + } +) + +var ( + maxSize = 200 // 姣忎釜鏃ュ織鏂囦欢鏈�澶у昂瀵�200M + maxBackups = 20 // 鏃ュ織鏂囦欢鏈�澶氫繚瀛�20涓浠� + maxAge = 30 // 淇濈暀鏈�澶уぉ鏁� + _logger *zap.Logger + _pool = buffer.NewPool() + c Conf + + ConsoleEncoder = "console" // 鎺у埗鍙拌緭鍑� + JsonEncoder = "json" // json杈撳嚭 +) + +// Init 鍒濆鍖栨棩蹇�. +func Init(conf Conf) { + c = conf + prefix, suffix := getFileSuffixPrefix(c.Path) + + infoPath := path.Join(prefix + ".info" + suffix) + errPath := path.Join(prefix + ".err" + suffix) + items := []logItem{ + { + FileName: infoPath, + Level: func(level zapcore.Level) bool { + return level <= zap.InfoLevel + }, + }, + { + FileName: errPath, + Level: func(level zapcore.Level) bool { + return level > zap.InfoLevel + }, + }, + } + + NewLogger(items) +} + +// NewLogger 鏃ュ織. +func NewLogger(items []logItem) { + var ( + cfg zapcore.Encoder + cores []zapcore.Core + ) + switch c.Encoder { + case JsonEncoder: + cfg = NewJsonLog().Config() + case ConsoleEncoder: + cfg = NewConsoleLog().Config() + default: + cfg = NewConsoleLog().Config() + } + + for _, v := range items { + hook := lumberjack.Logger{ + Filename: v.FileName, + MaxSize: maxSize, // 姣忎釜鏃ュ織鏂囦欢淇濆瓨鐨勬渶澶у昂瀵� 鍗曚綅锛歁 + MaxBackups: maxBackups, // 鏃ュ織鏂囦欢鏈�澶氫繚瀛樺灏戜釜澶囦唤 + MaxAge: maxAge, // 鏂囦欢鏈�澶氫繚瀛樺灏戝ぉ + Compress: true, // 鏄惁鍘嬬缉 + LocalTime: true, // 澶囦唤鏂囦欢鍚嶆湰鍦�/UTC鏃堕棿 + } + core := zapcore.NewCore( + cfg, // 缂栫爜鍣ㄩ厤缃�; + zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 鎵撳嵃鍒版帶鍒跺彴鍜屾枃浠� + v.Level, // 鏃ュ織绾у埆 + ) + cores = append(cores, core) + } + + // 寮�鍚紑鍙戞ā寮忥紝鍫嗘爤璺熻釜 + caller := zap.AddCaller() + // 寮�鍙戞ā寮� + development := zap.Development() + // 浜屾灏佽 + skip := zap.AddCallerSkip(1) + // 鏋勯�犳棩蹇� + _logger = zap.New(zapcore.NewTee(cores...), caller, development, skip) + return +} + +// GetEncoder 鑾峰彇鑷畾涔夌紪鐮佸櫒. +func GetEncoder() Encoder { + switch c.Encoder { + case JsonEncoder: + return NewJsonLog() + case ConsoleEncoder: + return NewConsoleLog() + default: + return NewConsoleLog() + } +} + +// GetLogger 鑾峰彇鏃ュ織璁板綍鍣�. +func GetLogger() *zap.Logger { + return _logger +} + +// getFileSuffixPrefix 鏂囦欢璺緞鍒囧壊 +func getFileSuffixPrefix(fileName string) (prefix, suffix string) { + paths, _ := path.Split(fileName) + base := path.Base(fileName) + suffix = path.Ext(fileName) + prefix = strings.TrimSuffix(base, suffix) + prefix = path.Join(paths, prefix) + return +} + +// getFilePath 鑷畾涔夎幏鍙栨枃浠惰矾寰�. +func getFilePath(ec zapcore.EntryCaller) string { + if !ec.Defined { + return "undefined" + } + buf := _pool.Get() + buf.AppendString(ec.Function) + buf.AppendByte(':') + buf.AppendInt(int64(ec.Line)) + caller := buf.String() + buf.Free() + return caller +} diff --git a/pkg/logx/json.go b/pkg/logx/json.go new file mode 100644 index 0000000..1d7d361 --- /dev/null +++ b/pkg/logx/json.go @@ -0,0 +1,91 @@ +package logx + +import ( + "fmt" + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "time" +) + +type JsonLog struct { + fields []zap.Field + val string +} + +// NewJsonLog 鑷畾涔夋坊鍔爈og field. +func NewJsonLog() Encoder { + return &JsonLog{fields: make([]zap.Field, 0)} +} + +// Config 鑷畾涔夐厤缃�. +func (slf *JsonLog) Config() zapcore.Encoder { + var ( + cfg = zap.NewProductionEncoderConfig() + ) + + // 鏃堕棿鏍煎紡鑷畾涔� + cfg.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { + enc.AppendString(t.Format("2006-01-02 15:04:05")) + } + // 鎵撳嵃璺緞鑷畾涔� + cfg.EncodeCaller = func(caller zapcore.EntryCaller, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(getFilePath(caller)) + } + // 绾у埆鏄剧ず鑷畾涔� + cfg.EncodeLevel = func(level zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) { + encoder.AppendString(level.String()) + } + return zapcore.NewJSONEncoder(cfg) +} + +// WithKey 娣诲姞鍗曚釜閿�. +func (slf *JsonLog) WithKey(key string) Encoder { + slf.val = slf.val + key + " " + return slf +} + +// WithField 娣诲姞瀛楁. +func (slf *JsonLog) WithField(key, val string) Encoder { + slf.fields = append(slf.fields, zap.String(key, val)) + return slf +} + +func (slf *JsonLog) Debug(msg string) { + _logger.Debug(slf.val+msg, slf.fields...) +} + +func (slf *JsonLog) Debugf(format string, v ...interface{}) { + _logger.Debug(fmt.Sprintf(slf.val+format, v...), slf.fields...) +} + +func (slf *JsonLog) Info(msg string) { + _logger.Info(slf.val+msg, slf.fields...) +} + +func (slf *JsonLog) Infof(format string, v ...interface{}) { + _logger.Info(fmt.Sprintf(slf.val+format, v...), slf.fields...) +} + +func (slf *JsonLog) Warn(msg string) { + _logger.Warn(slf.val+msg, slf.fields...) +} + +func (slf *JsonLog) Warnf(format string, v ...interface{}) { + _logger.Warn(fmt.Sprintf(slf.val+format, v...), slf.fields...) +} + +func (slf *JsonLog) Error(msg string) { + _logger.Error(slf.val+msg, slf.fields...) +} + +func (slf *JsonLog) Errorf(format string, v ...interface{}) { + _logger.Error(fmt.Sprintf(slf.val+format, v...), slf.fields...) +} + +func (slf *JsonLog) Fatal(msg string) { + _logger.Fatal(slf.val+msg, slf.fields...) +} + +func (slf *JsonLog) Fatalf(format string, v ...interface{}) { + _logger.Fatal(fmt.Sprintf(slf.val+format, v...), slf.fields...) +} diff --git a/pkg/logx/service.go b/pkg/logx/service.go new file mode 100644 index 0000000..4416eee --- /dev/null +++ b/pkg/logx/service.go @@ -0,0 +1,49 @@ +package logx + +import ( + "fmt" +) + +func Sync() { + _ = _logger.Sync() +} + +func Debug(msg string) { + _logger.Debug(msg) +} + +func Debugf(format string, v ...interface{}) { + _logger.Debug(fmt.Sprintf(format, v...)) +} + +func Info(msg string) { + _logger.Info(msg) +} + +func Infof(format string, v ...interface{}) { + _logger.Info(fmt.Sprintf(format, v...)) +} + +func Warn(msg string) { + _logger.Warn(msg) +} + +func Warnf(format string, v ...interface{}) { + _logger.Warn(fmt.Sprintf(format, v...)) +} + +func Error(msg string) { + _logger.Error(msg) +} + +func Errorf(format string, v ...interface{}) { + _logger.Error(fmt.Sprintf(format, v...)) +} + +func Fatal(msg string) { + _logger.Fatal(msg) +} + +func Fatalf(format string, v ...interface{}) { + _logger.Fatal(fmt.Sprintf(format, v...)) +} diff --git a/request/jwt.go b/request/jwt.go new file mode 100644 index 0000000..0e3b5a4 --- /dev/null +++ b/request/jwt.go @@ -0,0 +1,20 @@ +package request + +import ( + "github.com/dgrijalva/jwt-go" + "srm/constvar" +) + +// Custom claims structure +type CustomClaims struct { + BaseClaims + BufferTime int64 + jwt.StandardClaims +} + +type BaseClaims struct { + UserId string + Username string + ParentId string + UserType constvar.UserType +} -- Gitblit v1.8.0