mirror of
https://gitee.com/shikong-sk/gofiber-study
synced 2025-02-23 23:32:15 +08:00
添加 waf
添加 访问频率限制测试
This commit is contained in:
parent
72fb03ddbf
commit
d152df3a1d
@ -11,6 +11,7 @@ type BasicConfig struct {
|
|||||||
Jwt JwtConfig `yaml:"jwt"`
|
Jwt JwtConfig `yaml:"jwt"`
|
||||||
NanoId NanoIdConfig `yaml:"nanoId"`
|
NanoId NanoIdConfig `yaml:"nanoId"`
|
||||||
Captcha CaptchaConfig `yaml:"captcha"`
|
Captcha CaptchaConfig `yaml:"captcha"`
|
||||||
|
Waf Waf `yaml:"waf"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type NanoIdConfig struct {
|
type NanoIdConfig struct {
|
||||||
@ -69,3 +70,8 @@ type CaptchaConfig struct {
|
|||||||
//Expire 失效时间 (秒)
|
//Expire 失效时间 (秒)
|
||||||
Expire int64 `json:"expired"`
|
Expire int64 `json:"expired"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Waf struct {
|
||||||
|
//RateLimit 访问频率
|
||||||
|
RateLimit int64 `yaml:"rateLimit"`
|
||||||
|
}
|
||||||
|
@ -42,3 +42,6 @@ captcha:
|
|||||||
showLineOptions: 4
|
showLineOptions: 4
|
||||||
source: 1234567890qwertyuioplkjhgfdsazxcvbnm
|
source: 1234567890qwertyuioplkjhgfdsazxcvbnm
|
||||||
expire: 300
|
expire: 300
|
||||||
|
|
||||||
|
waf:
|
||||||
|
rateLimit: 100
|
@ -9,6 +9,7 @@ import (
|
|||||||
"gofiber.study.skcks.cn/global"
|
"gofiber.study.skcks.cn/global"
|
||||||
"gofiber.study.skcks.cn/model/dto"
|
"gofiber.study.skcks.cn/model/dto"
|
||||||
"gofiber.study.skcks.cn/model/vo"
|
"gofiber.study.skcks.cn/model/vo"
|
||||||
|
"gofiber.study.skcks.cn/services/waf"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -180,3 +181,24 @@ func (c *Controller) VerifyCaptchaTest() {
|
|||||||
return ctx.JSON(response.NewResponse("验证成功"))
|
return ctx.JSON(response.NewResponse("验证成功"))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WafRateLimitTest waf 访问频率限制 测试
|
||||||
|
//
|
||||||
|
// @Summary waf 访问频率限制 测试
|
||||||
|
// @Description waf 访问频率限制 测试
|
||||||
|
// @Tags Test
|
||||||
|
// @Accept json
|
||||||
|
// @Produce json
|
||||||
|
// @Success 200 {object} response.Response{data=string}
|
||||||
|
// @Failure default {object} errorx.CodeErrorResponse
|
||||||
|
// @Router /test/waf/access [get]
|
||||||
|
func (c *Controller) WafRateLimitTest() {
|
||||||
|
c.Router.Add(fiber.MethodGet, "/waf/access", func(ctx *fiber.Ctx) error {
|
||||||
|
access := waf.Service.Access(ctx.IP())
|
||||||
|
if !access {
|
||||||
|
return ctx.JSON(errorx.NewErrorWithCode(fiber.StatusTooManyRequests, "访问频率超过限制"))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ctx.JSON(response.NewResponse("正常访问"))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
46
docs/docs.go
46
docs/docs.go
@ -717,6 +717,47 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/test/waf/access": {
|
||||||
|
"get": {
|
||||||
|
"description": "waf 访问频率限制 测试",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Test"
|
||||||
|
],
|
||||||
|
"summary": "waf 访问频率限制 测试",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/errorx.CodeErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/account": {
|
"/user/account": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -928,6 +969,11 @@ const docTemplate = `{
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "data:image/png;base64,iVBO..."
|
"example": "data:image/png;base64,iVBO..."
|
||||||
},
|
},
|
||||||
|
"expire": {
|
||||||
|
"description": "过期时间 unix",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 10000000
|
||||||
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"description": "验证码 id",
|
"description": "验证码 id",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -709,6 +709,47 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/test/waf/access": {
|
||||||
|
"get": {
|
||||||
|
"description": "waf 访问频率限制 测试",
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"Test"
|
||||||
|
],
|
||||||
|
"summary": "waf 访问频率限制 测试",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "OK",
|
||||||
|
"schema": {
|
||||||
|
"allOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/definitions/response.Response"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"data": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"description": "",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/errorx.CodeErrorResponse"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/user/account": {
|
"/user/account": {
|
||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
@ -920,6 +961,11 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"example": "data:image/png;base64,iVBO..."
|
"example": "data:image/png;base64,iVBO..."
|
||||||
},
|
},
|
||||||
|
"expire": {
|
||||||
|
"description": "过期时间 unix",
|
||||||
|
"type": "integer",
|
||||||
|
"example": 10000000
|
||||||
|
},
|
||||||
"id": {
|
"id": {
|
||||||
"description": "验证码 id",
|
"description": "验证码 id",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
@ -106,6 +106,10 @@ definitions:
|
|||||||
description: 验证码图片 base64
|
description: 验证码图片 base64
|
||||||
example: data:image/png;base64,iVBO...
|
example: data:image/png;base64,iVBO...
|
||||||
type: string
|
type: string
|
||||||
|
expire:
|
||||||
|
description: 过期时间 unix
|
||||||
|
example: 10000000
|
||||||
|
type: integer
|
||||||
id:
|
id:
|
||||||
description: 验证码 id
|
description: 验证码 id
|
||||||
example: abcdefg123456
|
example: abcdefg123456
|
||||||
@ -556,6 +560,30 @@ paths:
|
|||||||
summary: sonyFlake id 生成测试
|
summary: sonyFlake id 生成测试
|
||||||
tags:
|
tags:
|
||||||
- Test
|
- Test
|
||||||
|
/test/waf/access:
|
||||||
|
get:
|
||||||
|
consumes:
|
||||||
|
- application/json
|
||||||
|
description: waf 访问频率限制 测试
|
||||||
|
produces:
|
||||||
|
- application/json
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
schema:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/definitions/response.Response'
|
||||||
|
- properties:
|
||||||
|
data:
|
||||||
|
type: string
|
||||||
|
type: object
|
||||||
|
default:
|
||||||
|
description: ""
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/errorx.CodeErrorResponse'
|
||||||
|
summary: waf 访问频率限制 测试
|
||||||
|
tags:
|
||||||
|
- Test
|
||||||
/user/account:
|
/user/account:
|
||||||
get:
|
get:
|
||||||
consumes:
|
consumes:
|
||||||
|
@ -11,6 +11,7 @@ targets:
|
|||||||
column_mapper: snake # how column name map to class or struct field name
|
column_mapper: snake # how column name map to class or struct field name
|
||||||
include_tables: # tables included, you can use **
|
include_tables: # tables included, you can use **
|
||||||
- user
|
- user
|
||||||
|
- waf
|
||||||
table_prefix: ""
|
table_prefix: ""
|
||||||
multiple_files: true # generate multiple files or one
|
multiple_files: true # generate multiple files or one
|
||||||
template: | # template for code file, it has higher perior than template_path
|
template: | # template for code file, it has higher perior than template_path
|
||||||
|
@ -3,9 +3,11 @@ package services
|
|||||||
import (
|
import (
|
||||||
"gofiber.study.skcks.cn/services/auth"
|
"gofiber.study.skcks.cn/services/auth"
|
||||||
"gofiber.study.skcks.cn/services/user"
|
"gofiber.study.skcks.cn/services/user"
|
||||||
|
"gofiber.study.skcks.cn/services/waf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Init() {
|
func Init() {
|
||||||
auth.InitService()
|
auth.InitService()
|
||||||
user.InitService()
|
user.InitService()
|
||||||
|
waf.InitService()
|
||||||
}
|
}
|
||||||
|
67
services/waf/waf.go
Normal file
67
services/waf/waf.go
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package waf
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"github.com/go-redis/redis/v8"
|
||||||
|
"gofiber.study.skcks.cn/common/config"
|
||||||
|
"gofiber.study.skcks.cn/common/logger"
|
||||||
|
"gofiber.study.skcks.cn/global"
|
||||||
|
"time"
|
||||||
|
"xorm.io/xorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
var Service *Waf
|
||||||
|
|
||||||
|
const (
|
||||||
|
StoreName = "waf"
|
||||||
|
Separator = ":"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Waf struct {
|
||||||
|
db *xorm.EngineGroup
|
||||||
|
store *redis.Client
|
||||||
|
config config.Waf
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitService() {
|
||||||
|
Service = &Waf{
|
||||||
|
db: global.DataSources,
|
||||||
|
store: global.Redis,
|
||||||
|
config: global.Config.Waf,
|
||||||
|
}
|
||||||
|
//
|
||||||
|
//ctx := context.Background()
|
||||||
|
//table, err := Service.store.HGetAll(ctx, StoreName).Result()
|
||||||
|
//utils.MainAppExec(func() {
|
||||||
|
// if err != nil {
|
||||||
|
// logger.Log.Errorf("[waf] 初始化出错 %s", err)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// logger.Log.Debugf("[waf] \n%v", table)
|
||||||
|
//})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *Waf) Access(ip string) bool {
|
||||||
|
key := StoreName + Separator + "access" + Separator + ip
|
||||||
|
ctx := context.Background()
|
||||||
|
num, err := w.store.LLen(ctx, key).Result()
|
||||||
|
if err != nil {
|
||||||
|
logger.Log.Errorf("[waf] access 出错 %s", err)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if num < w.config.RateLimit {
|
||||||
|
w.store.LPush(ctx, key, time.Now().Unix())
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
last, _ := w.store.LIndex(ctx, key, -1).Int64()
|
||||||
|
if time.Now().Unix()-last < 60 {
|
||||||
|
logger.Log.Infof("[waf] ip:%s 访问频率超过限制 %d", ip, w.config.RateLimit)
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
w.store.LPush(ctx, key, time.Now().Unix())
|
||||||
|
w.store.LTrim(ctx, key, 0, w.config.RateLimit-1)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user