Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
new-api
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
ff2e0dbc
authored
Aug 10, 2025
by
creamlike1024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(middleware): add email verification rate limit
parent
8217e694
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
86 additions
and
16 deletions
+86
-16
middleware/email-verification-rate-limit.go
+70
-0
router/api-router.go
+16
-16
No files found.
middleware/email-verification-rate-limit.go
0 → 100644
View file @
ff2e0dbc
package
middleware
import
(
"context"
"fmt"
"net/http"
"one-api/common"
"time"
"github.com/gin-gonic/gin"
)
const
(
EmailVerificationRateLimitMark
=
"EV"
EmailVerificationMaxRequests
=
2
// 30秒内最多2次
EmailVerificationDuration
=
30
// 30秒时间窗口
)
func
redisEmailVerificationRateLimiter
(
c
*
gin
.
Context
)
{
ctx
:=
context
.
Background
()
rdb
:=
common
.
RDB
key
:=
"emailVerification:"
+
EmailVerificationRateLimitMark
+
":"
+
c
.
ClientIP
()
listLength
,
err
:=
rdb
.
LLen
(
ctx
,
key
)
.
Result
()
if
err
!=
nil
{
fmt
.
Println
(
"Redis限流检查失败:"
,
err
.
Error
())
c
.
Status
(
http
.
StatusInternalServerError
)
c
.
Abort
()
return
}
if
listLength
<
EmailVerificationMaxRequests
{
rdb
.
LPush
(
ctx
,
key
,
time
.
Now
()
.
Format
(
timeFormat
))
rdb
.
Expire
(
ctx
,
key
,
time
.
Duration
(
EmailVerificationDuration
)
*
time
.
Second
)
c
.
Next
()
return
}
c
.
JSON
(
http
.
StatusTooManyRequests
,
gin
.
H
{
"success"
:
false
,
"message"
:
fmt
.
Sprintf
(
"发送过于频繁,请等待 %d 秒后再试"
,
EmailVerificationDuration
),
})
c
.
Abort
()
}
func
memoryEmailVerificationRateLimiter
(
c
*
gin
.
Context
)
{
key
:=
EmailVerificationRateLimitMark
+
":"
+
c
.
ClientIP
()
if
!
inMemoryRateLimiter
.
Request
(
key
,
EmailVerificationMaxRequests
,
EmailVerificationDuration
)
{
c
.
JSON
(
http
.
StatusTooManyRequests
,
gin
.
H
{
"success"
:
false
,
"message"
:
"发送过于频繁,请稍后再试"
,
})
c
.
Abort
()
return
}
c
.
Next
()
}
func
EmailVerificationRateLimit
()
gin
.
HandlerFunc
{
return
func
(
c
*
gin
.
Context
)
{
if
common
.
RedisEnabled
{
redisEmailVerificationRateLimiter
(
c
)
}
else
{
inMemoryRateLimiter
.
Init
(
common
.
RateLimitKeyExpirationDuration
)
memoryEmailVerificationRateLimiter
(
c
)
}
}
}
router/api-router.go
View file @
ff2e0dbc
...
...
@@ -24,7 +24,7 @@ func SetApiRouter(router *gin.Engine) {
//apiRouter.GET("/midjourney", controller.GetMidjourney)
apiRouter
.
GET
(
"/home_page_content"
,
controller
.
GetHomePageContent
)
apiRouter
.
GET
(
"/pricing"
,
middleware
.
TryUserAuth
(),
controller
.
GetPricing
)
apiRouter
.
GET
(
"/verification"
,
middleware
.
Critical
RateLimit
(),
middleware
.
TurnstileCheck
(),
controller
.
SendEmailVerification
)
apiRouter
.
GET
(
"/verification"
,
middleware
.
EmailVerification
RateLimit
(),
middleware
.
TurnstileCheck
(),
controller
.
SendEmailVerification
)
apiRouter
.
GET
(
"/reset_password"
,
middleware
.
CriticalRateLimit
(),
middleware
.
TurnstileCheck
(),
controller
.
SendPasswordResetEmail
)
apiRouter
.
POST
(
"/user/reset"
,
middleware
.
CriticalRateLimit
(),
controller
.
ResetPassword
)
apiRouter
.
GET
(
"/oauth/github"
,
middleware
.
CriticalRateLimit
(),
controller
.
GitHubOAuth
)
...
...
@@ -67,7 +67,7 @@ func SetApiRouter(router *gin.Engine) {
selfRoute
.
POST
(
"/stripe/amount"
,
controller
.
RequestStripeAmount
)
selfRoute
.
POST
(
"/aff_transfer"
,
controller
.
TransferAffQuota
)
selfRoute
.
PUT
(
"/setting"
,
controller
.
UpdateUserSetting
)
// 2FA routes
selfRoute
.
GET
(
"/2fa/status"
,
controller
.
Get2FAStatus
)
selfRoute
.
POST
(
"/2fa/setup"
,
controller
.
Setup2FA
)
...
...
@@ -86,7 +86,7 @@ func SetApiRouter(router *gin.Engine) {
adminRoute
.
POST
(
"/manage"
,
controller
.
ManageUser
)
adminRoute
.
PUT
(
"/"
,
controller
.
UpdateUser
)
adminRoute
.
DELETE
(
"/:id"
,
controller
.
DeleteUser
)
// Admin 2FA routes
adminRoute
.
GET
(
"/2fa/stats"
,
controller
.
Admin2FAStats
)
adminRoute
.
DELETE
(
"/:id/2fa"
,
controller
.
AdminDisable2FA
)
...
...
@@ -200,22 +200,22 @@ func SetApiRouter(router *gin.Engine) {
}
vendorRoute
:=
apiRouter
.
Group
(
"/vendors"
)
vendorRoute
.
Use
(
middleware
.
AdminAuth
())
{
vendorRoute
.
GET
(
"/"
,
controller
.
GetAllVendors
)
vendorRoute
.
GET
(
"/search"
,
controller
.
SearchVendors
)
vendorRoute
.
GET
(
"/:id"
,
controller
.
GetVendorMeta
)
vendorRoute
.
POST
(
"/"
,
controller
.
CreateVendorMeta
)
vendorRoute
.
PUT
(
"/"
,
controller
.
UpdateVendorMeta
)
vendorRoute
.
DELETE
(
"/:id"
,
controller
.
DeleteVendorMeta
)
}
modelsRoute
:=
apiRouter
.
Group
(
"/models"
)
vendorRoute
.
Use
(
middleware
.
AdminAuth
())
{
vendorRoute
.
GET
(
"/"
,
controller
.
GetAllVendors
)
vendorRoute
.
GET
(
"/search"
,
controller
.
SearchVendors
)
vendorRoute
.
GET
(
"/:id"
,
controller
.
GetVendorMeta
)
vendorRoute
.
POST
(
"/"
,
controller
.
CreateVendorMeta
)
vendorRoute
.
PUT
(
"/"
,
controller
.
UpdateVendorMeta
)
vendorRoute
.
DELETE
(
"/:id"
,
controller
.
DeleteVendorMeta
)
}
modelsRoute
:=
apiRouter
.
Group
(
"/models"
)
modelsRoute
.
Use
(
middleware
.
AdminAuth
())
{
modelsRoute
.
GET
(
"/missing"
,
controller
.
GetMissingModels
)
modelsRoute
.
GET
(
"/"
,
controller
.
GetAllModelsMeta
)
modelsRoute
.
GET
(
"/search"
,
controller
.
SearchModelsMeta
)
modelsRoute
.
GET
(
"/"
,
controller
.
GetAllModelsMeta
)
modelsRoute
.
GET
(
"/search"
,
controller
.
SearchModelsMeta
)
modelsRoute
.
GET
(
"/:id"
,
controller
.
GetModelMeta
)
modelsRoute
.
POST
(
"/"
,
controller
.
CreateModelMeta
)
modelsRoute
.
PUT
(
"/"
,
controller
.
UpdateModelMeta
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment