@@ -0,0 +1,103 @@
|
||||
package ipblock
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"91porn-server/app/appg"
|
||||
"91porn-server/common"
|
||||
"91porn-server/common/constant"
|
||||
"91porn-server/common/constant/redisconst"
|
||||
"91porn-server/common/stderr"
|
||||
"91porn-server/models/v/ipblockmod"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func IPBlock(blockType string) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
if !appg.ShouldEnforceIPRateLimit() {
|
||||
return
|
||||
}
|
||||
ip := common.GetIP(ctx)
|
||||
key := redisconst.IPBlockKey(blockType)
|
||||
if count, err := appg.Redis.SCard(key); count == 0 || err != nil {
|
||||
ipdata, err := ipblockmod.AggregateForIPArray(blockType)
|
||||
if err == nil && len(ipdata.IPS) > 0 {
|
||||
// 仅在集合为空时回源重建:直接 SAdd,去掉 Del 以消除"先删后加"的空窗期漏拦;
|
||||
// TTL 设在 key 自身(此前误用 IPBlockKey(key) 二次包裹成 ip:block:ip:block:xxx,
|
||||
// 导致真实集合永不过期、永不回源刷新)
|
||||
_, _ = appg.Redis.SAdd(key, ipdata.IPS)
|
||||
_, _ = appg.Redis.ExpireKey(key, redisconst.IPBlockExpire)
|
||||
}
|
||||
}
|
||||
isBlock, err := appg.Redis.SISMember(key, ip)
|
||||
//表示当前IP在限制名单中
|
||||
if isBlock && err == nil {
|
||||
ctx.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
"code": stderr.ErrReqForbidden,
|
||||
"msg": stderr.ErrReqForbidden.Msg(),
|
||||
"tip": stderr.ErrReqForbidden.Tip(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func IPAutoBlock(blockType string, duration time.Duration, count int64) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
if !appg.ShouldEnforceIPRateLimit() {
|
||||
return
|
||||
}
|
||||
ip := common.GetIP(ctx)
|
||||
if ip != "" {
|
||||
key := redisconst.IPAutoBlockKey(blockType, ip)
|
||||
cnt := appg.Redis.Incr(key)
|
||||
if cnt == 1 {
|
||||
_, _ = appg.Redis.ExpireKey(key, duration)
|
||||
}
|
||||
if cnt >= count {
|
||||
switch blockType {
|
||||
case constant.Register:
|
||||
ctx.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
"code": stderr.ErrLoginTooFrequently,
|
||||
"msg": stderr.ErrLoginTooFrequently.Msg(),
|
||||
"tip": stderr.ErrLoginTooFrequently.Tip(),
|
||||
})
|
||||
default:
|
||||
ctx.AbortWithStatusJSON(http.StatusOK, gin.H{
|
||||
"code": stderr.ErrReqForbidden,
|
||||
"msg": stderr.ErrReqForbidden.Msg(),
|
||||
"tip": stderr.ErrReqForbidden.Tip(),
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CountAutoBlock(blockType string, duration time.Duration, count int64) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
var key string
|
||||
switch blockType {
|
||||
case constant.BlockComment:
|
||||
uid, err := common.GetUID(ctx)
|
||||
if err == nil {
|
||||
key = redisconst.AutoBlockKey(blockType, uid)
|
||||
}
|
||||
}
|
||||
cnt := appg.Redis.Incr(key)
|
||||
if cnt == 1 {
|
||||
_, _ = appg.Redis.ExpireKey(key, duration)
|
||||
}
|
||||
if cnt > count {
|
||||
ctx.AbortWithStatusJSON(http.StatusServiceUnavailable, gin.H{
|
||||
"code": stderr.ErrReqForbidden,
|
||||
"msg": stderr.ErrReqForbidden.Msg(),
|
||||
"tip": stderr.ErrReqForbidden.Tip(),
|
||||
})
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user