BREAKING CHANGE: The original Go module name was `github.com/ArtalkJS/Artalk`, which has now been modified to `github.com/artalkjs/artalk/v2` (all lowercase). This change may affect the CI pipeline or other areas if you are compiling the Artalk server and have specified the fixed Go module name. Regarding the original `-ldflags -X github.com/ArtalkJS/Artalk/internal/config.Version` and `CommitHash` definitions, please remove them, as they are now obsolete. The `Version` has been hardcoded into the Go code, and the `CommitHash` is now read from the Go build info via runtime/debug’s vcs.revision value. This change only affects the server developers and does not impact the frontend UI client.
83 lines
1.8 KiB
Go
83 lines
1.8 KiB
Go
package common
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/artalkjs/artalk/v2/internal/captcha"
|
|
"github.com/artalkjs/artalk/v2/internal/core"
|
|
"github.com/artalkjs/artalk/v2/internal/i18n"
|
|
"github.com/artalkjs/artalk/v2/server/middleware/limiter"
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
func GetLimiter(c *fiber.Ctx) (lmt *limiter.Limiter, err error) {
|
|
l, ok := c.Locals("limiter").(*limiter.Limiter)
|
|
if l == nil || !ok {
|
|
return nil, RespError(c, 500, "limiter is not initialize, but middleware is used")
|
|
}
|
|
return l, nil
|
|
}
|
|
|
|
func NewCaptchaChecker(app *core.App, c *fiber.Ctx) captcha.Checker {
|
|
user, _ := GetUserByReq(app, c)
|
|
return captcha.NewCaptchaChecker(&captcha.CheckerConf{
|
|
CaptchaConf: app.Conf().Captcha,
|
|
User: captcha.User{
|
|
ID: fmt.Sprint(user.ID),
|
|
IP: c.IP(),
|
|
},
|
|
})
|
|
}
|
|
|
|
func LimiterGuard(app *core.App, handler fiber.Handler) fiber.Handler {
|
|
return func(c *fiber.Ctx) error {
|
|
limiter, err := GetLimiter(c)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 关闭验证码功能,直接 Skip
|
|
if !app.Conf().Captcha.Enabled {
|
|
return handler(c)
|
|
}
|
|
|
|
// 管理员直接忽略
|
|
if CheckIsAdminReq(app, c) {
|
|
return handler(c)
|
|
}
|
|
|
|
// 检测是否需要验证码
|
|
ip := c.IP()
|
|
if limiter.IsPass(ip) {
|
|
// 无需验证码
|
|
err := handler(c)
|
|
|
|
if c.Method() != fiber.MethodOptions { // 忽略 Options 请求
|
|
limiter.Log(ip) // 记录操作
|
|
}
|
|
|
|
return err
|
|
} else {
|
|
// create new captcha checker instance
|
|
cap := NewCaptchaChecker(app, c)
|
|
|
|
// response need captcha check
|
|
respData := Map{
|
|
"need_captcha": true,
|
|
}
|
|
|
|
switch cap.Type() {
|
|
case captcha.Image:
|
|
// 图片验证码
|
|
img, _ := cap.Get()
|
|
respData["img_data"] = string(img)
|
|
case captcha.IFrame:
|
|
// iFrame 验证模式
|
|
respData["iframe"] = true
|
|
}
|
|
|
|
return RespError(c, 403, i18n.T("Captcha required"), respData)
|
|
}
|
|
}
|
|
}
|