Browse Source

Merge remote-tracking branch 'origin/update' into update

main
piexlmax 3 years ago
parent
commit
455dad13e6
  1. 68
      server/middleware/limit_ip.go
  2. 87
      server/middleware/logger.go

68
server/middleware/limit_ip.go

@ -3,37 +3,77 @@ package middleware
import ( import (
"context" "context"
"errors" "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/global"
"github.com/flipped-aurora/gin-vue-admin/server/model/common/response" "github.com/flipped-aurora/gin-vue-admin/server/model/common/response"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"time"
) )
// ip限制
func IPLimit() gin.HandlerFunc {
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) { return func(c *gin.Context) {
key := "RequestClientIPLimit===" + c.ClientIP()
limit := global.GVA_CONFIG.System.LimitCountIP
second := global.GVA_CONFIG.System.LimitTimeIP
expiration := time.Duration(second) * time.Second
if err := SetLimitWithTime(key, limit, expiration); err != nil {
response.FailWithMessage(err.Error(), c)
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() c.Abort()
return return
}
// 继续往下处理
} else {
c.Next() 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 { func SetLimitWithTime(key string, limit int, expiration time.Duration) error {
count, err := global.GVA_REDIS.Exists(context.Background(), key).Result() count, err := global.GVA_REDIS.Exists(context.Background(), key).Result()
if err != nil || count == 0 {
if err != nil {
return err
}
if count == 0 {
pipe := global.GVA_REDIS.TxPipeline() pipe := global.GVA_REDIS.TxPipeline()
pipe.Incr(context.Background(), key) pipe.Incr(context.Background(), key)
pipe.Expire(context.Background(), key, expiration) pipe.Expire(context.Background(), key, expiration)
_, err := pipe.Exec(context.Background())
_, err = pipe.Exec(context.Background())
return err return err
} else { } else {
//次数 //次数

87
server/middleware/logger.go

@ -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()
}
Loading…
Cancel
Save