奇淼(piexlmax
3 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 743 additions and 689 deletions
-
5server/config.yaml
-
2server/config/system.go
-
1server/config/zap.go
-
2server/core/server.go
-
54server/core/zap.go
-
7server/go.mod
-
15server/go.sum
-
94server/middleware/limit_ip.go
-
87server/middleware/logger.go
-
6server/service/system/sys_auto_code.go
-
5server/service/system/sys_autocode_history.go
-
6server/utils/file_operations.go
-
28server/utils/rotatelogs.go
-
32server/utils/rotatelogs_unix.go
-
28server/utils/rotatelogs_windows.go
-
459web/package-lock.json
-
2web/package.json
-
2web/src/core/gin-vue-admin.js
-
2web/src/view/layout/bottomInfo/bottomInfo.vue
-
595web/src/view/systemTools/system/system.vue
@ -0,0 +1,94 @@ |
|||
package middleware |
|||
|
|||
import ( |
|||
"context" |
|||
"errors" |
|||
"net/http" |
|||
"time" |
|||
|
|||
"go.uber.org/zap" |
|||
|
|||
"github.com/flipped-aurora/gin-vue-admin/server/global" |
|||
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response" |
|||
"github.com/gin-gonic/gin" |
|||
) |
|||
|
|||
type LimitConfig struct { |
|||
// GenerationKey 根据业务生成key 下面CheckOrMark查询生成
|
|||
GenerationKey func(c *gin.Context) string |
|||
// 检查函数,用户可修改具体逻辑,更加灵活
|
|||
CheckOrMark func(key string, expire int, limit int) error |
|||
// Expire key 过期时间
|
|||
Expire int |
|||
// Limit 周期时间
|
|||
Limit int |
|||
} |
|||
|
|||
func (l LimitConfig) LimitWithTime() gin.HandlerFunc { |
|||
return func(c *gin.Context) { |
|||
if err := l.CheckOrMark(l.GenerationKey(c), l.Expire, l.Limit); err != nil { |
|||
c.JSON(http.StatusOK, gin.H{"code": response.ERROR, "msg": err}) |
|||
c.Abort() |
|||
return |
|||
} else { |
|||
c.Next() |
|||
} |
|||
} |
|||
} |
|||
|
|||
// DefaultGenerationKey 默认生成key
|
|||
func DefaultGenerationKey(c *gin.Context) string { |
|||
return "GVA_Limit" + c.ClientIP() |
|||
} |
|||
|
|||
func DefaultCheckOrMark(key string, expire int, limit int) (err error) { |
|||
// 判断是否开启redis
|
|||
if global.GVA_REDIS == nil { |
|||
return err |
|||
} |
|||
if err = SetLimitWithTime(key, limit, time.Duration(expire)*time.Second); err != nil { |
|||
global.GVA_LOG.Error("limit", zap.Error(err)) |
|||
|
|||
} |
|||
return err |
|||
|
|||
} |
|||
|
|||
func DefaultLimit() gin.HandlerFunc { |
|||
return LimitConfig{ |
|||
GenerationKey: DefaultGenerationKey, |
|||
CheckOrMark: DefaultCheckOrMark, |
|||
Expire: global.GVA_CONFIG.System.LimitTimeIP, |
|||
Limit: global.GVA_CONFIG.System.LimitCountIP, |
|||
}.LimitWithTime() |
|||
} |
|||
|
|||
// SetLimitWithTime 设置访问次数
|
|||
func SetLimitWithTime(key string, limit int, expiration time.Duration) error { |
|||
count, err := global.GVA_REDIS.Exists(context.Background(), key).Result() |
|||
if err != nil { |
|||
return err |
|||
} |
|||
if count == 0 { |
|||
pipe := global.GVA_REDIS.TxPipeline() |
|||
pipe.Incr(context.Background(), key) |
|||
pipe.Expire(context.Background(), key, expiration) |
|||
_, err = pipe.Exec(context.Background()) |
|||
return err |
|||
} else { |
|||
//次数
|
|||
if times, err := global.GVA_REDIS.Get(context.Background(), key).Int(); err != nil { |
|||
return err |
|||
} else { |
|||
if times >= limit { |
|||
if t, err := global.GVA_REDIS.PTTL(context.Background(), key).Result(); err != nil { |
|||
return errors.New("请求太过频繁,请稍后再试") |
|||
} else { |
|||
return errors.New("请求太过频繁, 请 " + t.String() + " 秒后尝试") |
|||
} |
|||
} else { |
|||
return global.GVA_REDIS.Incr(context.Background(), key).Err() |
|||
} |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,87 @@ |
|||
package middleware |
|||
|
|||
import ( |
|||
"bytes" |
|||
"encoding/json" |
|||
"fmt" |
|||
"io/ioutil" |
|||
"strings" |
|||
"time" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
) |
|||
|
|||
// LogLayout 日志layout
|
|||
type LogLayout struct { |
|||
Time time.Time |
|||
Metadata map[string]interface{} // 存储自定义原数据
|
|||
Path string // 访问路径
|
|||
Query string // 携带query
|
|||
Body string // 携带body数据
|
|||
IP string // ip地址
|
|||
UserAgent string // 代理
|
|||
Error string // 错误
|
|||
Cost time.Duration // 花费时间
|
|||
Source string // 来源
|
|||
} |
|||
|
|||
type Logger struct { |
|||
// Filter 用户自定义过滤
|
|||
Filter func(c *gin.Context) bool |
|||
// FilterKeyword 关键字过滤(key)
|
|||
FilterKeyword func(layout *LogLayout) bool |
|||
// AuthProcess 鉴权处理
|
|||
AuthProcess func(c *gin.Context, layout *LogLayout) |
|||
// 日志处理
|
|||
Print func(LogLayout) |
|||
// Source 服务唯一标识
|
|||
Source string |
|||
} |
|||
|
|||
func (l Logger) SetLoggerMiddleware() gin.HandlerFunc { |
|||
return func(c *gin.Context) { |
|||
start := time.Now() |
|||
path := c.Request.URL.Path |
|||
query := c.Request.URL.RawQuery |
|||
var body []byte |
|||
if l.Filter != nil && !l.Filter(c) { |
|||
body, _ = c.GetRawData() |
|||
// 将原body塞回去
|
|||
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body)) |
|||
} |
|||
c.Next() |
|||
cost := time.Since(start) |
|||
layout := LogLayout{ |
|||
Time: time.Now(), |
|||
Path: path, |
|||
Query: query, |
|||
IP: c.ClientIP(), |
|||
UserAgent: c.Request.UserAgent(), |
|||
Error: strings.TrimRight(c.Errors.ByType(gin.ErrorTypePrivate).String(), "\n"), |
|||
Cost: cost, |
|||
Source: l.Source, |
|||
} |
|||
if l.Filter != nil && !l.Filter(c) { |
|||
layout.Body = string(body) |
|||
} |
|||
// 处理鉴权需要的信息
|
|||
l.AuthProcess(c, &layout) |
|||
if l.FilterKeyword != nil { |
|||
// 自行判断key/value 脱敏等
|
|||
l.FilterKeyword(&layout) |
|||
} |
|||
// 自行处理日志
|
|||
l.Print(layout) |
|||
} |
|||
} |
|||
|
|||
func DefaultLogger() gin.HandlerFunc { |
|||
return Logger{ |
|||
Print: func(layout LogLayout) { |
|||
// 标准输出,k8s做收集
|
|||
v, _ := json.Marshal(layout) |
|||
fmt.Println(string(v)) |
|||
}, |
|||
Source: "GVA", |
|||
}.SetLoggerMiddleware() |
|||
} |
@ -0,0 +1,28 @@ |
|||
package utils |
|||
|
|||
import ( |
|||
"github.com/flipped-aurora/gin-vue-admin/server/global" |
|||
"github.com/natefinch/lumberjack" |
|||
"go.uber.org/zap/zapcore" |
|||
"os" |
|||
) |
|||
|
|||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
|||
//@function: GetWriteSyncer
|
|||
//@description: zap logger中加入file-rotatelogs
|
|||
//@return: zapcore.WriteSyncer, error
|
|||
|
|||
func GetWriteSyncer(file string) zapcore.WriteSyncer { |
|||
lumberJackLogger := &lumberjack.Logger{ |
|||
Filename: file, //日志文件的位置
|
|||
MaxSize: 10, //在进行切割之前,日志文件的最大大小(以MB为单位)
|
|||
MaxBackups: 200, //保留旧文件的最大个数
|
|||
MaxAge: 30, //保留旧文件的最大天数
|
|||
Compress: true, //是否压缩/归档旧文件
|
|||
} |
|||
|
|||
if global.GVA_CONFIG.Zap.LogInConsole { |
|||
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger)) |
|||
} |
|||
return zapcore.AddSync(lumberJackLogger) |
|||
} |
@ -1,32 +0,0 @@ |
|||
//go:build !windows
|
|||
// +build !windows
|
|||
|
|||
package utils |
|||
|
|||
import ( |
|||
"os" |
|||
"path" |
|||
"time" |
|||
|
|||
"github.com/flipped-aurora/gin-vue-admin/server/global" |
|||
zaprotatelogs "github.com/lestrrat-go/file-rotatelogs" |
|||
"go.uber.org/zap/zapcore" |
|||
) |
|||
|
|||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
|||
//@function: GetWriteSyncer
|
|||
//@description: zap logger中加入file-rotatelogs
|
|||
//@return: zapcore.WriteSyncer, error
|
|||
|
|||
func GetWriteSyncer() (zapcore.WriteSyncer, error) { |
|||
fileWriter, err := zaprotatelogs.New( |
|||
path.Join(global.GVA_CONFIG.Zap.Director, "%Y-%m-%d.log"), |
|||
zaprotatelogs.WithLinkName(global.GVA_CONFIG.Zap.LinkName), |
|||
zaprotatelogs.WithMaxAge(7*24*time.Hour), |
|||
zaprotatelogs.WithRotationTime(24*time.Hour), |
|||
) |
|||
if global.GVA_CONFIG.Zap.LogInConsole { |
|||
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileWriter)), err |
|||
} |
|||
return zapcore.AddSync(fileWriter), err |
|||
} |
@ -1,28 +0,0 @@ |
|||
package utils |
|||
|
|||
import ( |
|||
"os" |
|||
"path" |
|||
"time" |
|||
|
|||
"github.com/flipped-aurora/gin-vue-admin/server/global" |
|||
zaprotatelogs "github.com/lestrrat-go/file-rotatelogs" |
|||
"go.uber.org/zap/zapcore" |
|||
) |
|||
|
|||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
|||
//@function: GetWriteSyncer
|
|||
//@description: zap logger中加入file-rotatelogs
|
|||
//@return: zapcore.WriteSyncer, error
|
|||
|
|||
func GetWriteSyncer() (zapcore.WriteSyncer, error) { |
|||
fileWriter, err := zaprotatelogs.New( |
|||
path.Join(global.GVA_CONFIG.Zap.Director, "%Y-%m-%d.log"), |
|||
zaprotatelogs.WithMaxAge(7*24*time.Hour), |
|||
zaprotatelogs.WithRotationTime(24*time.Hour), |
|||
) |
|||
if global.GVA_CONFIG.Zap.LogInConsole { |
|||
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(fileWriter)), err |
|||
} |
|||
return zapcore.AddSync(fileWriter), err |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue