验证码配置重构完成

This commit is contained in:
RockYang
2025-08-29 17:45:31 +08:00
parent 539e91c12e
commit 3a6f8ccc16
32 changed files with 272 additions and 248 deletions

View File

@@ -94,7 +94,6 @@ type BaseConfig struct {
DefaultNickname string `json:"default_nickname"` // 默认昵称
ICP string `json:"icp"` // ICP 备案号
EnabledVerify bool `json:"enabled_verify"` // 是否启用验证码
EmailWhiteList []string `json:"email_white_list"` // 邮箱白名单列表
AssistantModelId int `json:"assistant_model_id"` // 用来做提示词,翻译的AI模型 id
MaxFileSize int `json:"max_file_size"` // 最大文件大小,单位MB
@@ -118,6 +117,7 @@ const (
ConfigKeyNotice = "notice"
ConfigKeyAgreement = "agreement"
ConfigKeyPrivacy = "privacy"
ConfigKeyMarkMap = "mark_map"
ConfigKeyCaptcha = "captcha"
ConfigKeyWxLogin = "wx_login"
ConfigKeyLicense = "license"

View File

@@ -81,18 +81,18 @@ func (h *ManagerHandler) Login(c *gin.Context) {
return
}
if h.App.SysConfig.Base.EnabledVerify {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
} else {
check = h.captcha.Check(data)
}
if !check {
resp.ERROR(c, "请先完人机验证")
return
}
}
// if h.App.SysConfig.Base.EnabledVerify {
// var check bool
// if data.X != 0 {
// check = h.captcha.SlideCheck(data)
// } else {
// check = h.captcha.Check(data)
// }
// if !check {
// resp.ERROR(c, "请先完人机验证")
// return
// }
// }
var manager model.AdminUser
res := h.DB.Model(&model.AdminUser{}).Where("username = ?", data.Username).First(&manager)

View File

@@ -92,6 +92,9 @@ func (h *ConfigHandler) RegisterRoutes() {
rg.POST("update/base", h.UpdateBase)
rg.POST("update/power", h.UpdatePower)
rg.POST("update/notice", h.UpdateNotice)
rg.POST("update/agreement", h.UpdateAgreement)
rg.POST("update/privacy", h.UpdatePrivacy)
rg.POST("update/mark_map", h.UpdateMarkMap)
rg.POST("update/captcha", h.UpdateCaptcha)
rg.POST("update/wx_login", h.UpdateWxLogin)
rg.POST("update/payment", h.UpdatePayment)
@@ -193,6 +196,64 @@ func (h *ConfigHandler) UpdateNotice(c *gin.Context) {
resp.SUCCESS(c, data)
}
// UpdateAgreement 更新用户协议配置
func (h *ConfigHandler) UpdateAgreement(c *gin.Context) {
var data struct {
Content string `json:"content"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
err := h.Update(types.ConfigKeyAgreement, data)
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c, data)
}
// UpdatePrivacy 更新隐私政策配置
func (h *ConfigHandler) UpdatePrivacy(c *gin.Context) {
var data struct {
Content string `json:"content"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
err := h.Update(types.ConfigKeyPrivacy, data)
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c, data)
}
// UpdateMarkMap 更新思维导图配置
func (h *ConfigHandler) UpdateMarkMap(c *gin.Context) {
var data struct {
Content string `json:"content"`
}
if err := c.ShouldBindJSON(&data); err != nil {
resp.ERROR(c, types.InvalidArgs)
return
}
err := h.Update(types.ConfigKeyMarkMap, data)
if err != nil {
resp.ERROR(c, err.Error())
return
}
resp.SUCCESS(c, data)
}
// UpdateCaptcha 更新行为验证码配置
func (h *ConfigHandler) UpdateCaptcha(c *gin.Context) {
var data types.CaptchaConfig
@@ -206,10 +267,7 @@ func (h *ConfigHandler) UpdateCaptcha(c *gin.Context) {
resp.ERROR(c, err.Error())
return
}
if data.Enabled {
h.captchaService.UpdateConfig(data)
}
h.sysConfig.Captcha = data
h.captchaService.UpdateConfig(data)
resp.SUCCESS(c, data)
}

View File

@@ -16,16 +16,13 @@ import (
"github.com/gin-gonic/gin"
)
// 今日头条函数实现
type CaptchaHandler struct {
App *core.AppServer
service *service.CaptchaService
config types.CaptchaConfig
}
func NewCaptchaHandler(app *core.AppServer, s *service.CaptchaService, sysConfig *types.SystemConfig) *CaptchaHandler {
return &CaptchaHandler{App: app, service: s, config: sysConfig.Captcha}
return &CaptchaHandler{App: app, service: s}
}
// RegisterRoutes 注册路由
@@ -37,10 +34,15 @@ func (h *CaptchaHandler) RegisterRoutes() {
group.POST("check", h.Check)
group.GET("slide/get", h.SlideGet)
group.POST("slide/check", h.SlideCheck)
group.GET("config", h.GetConfig)
}
func (h *CaptchaHandler) GetConfig(c *gin.Context) {
resp.SUCCESS(c, gin.H{"enabled": h.service.GetConfig().Enabled, "type": h.service.GetConfig().Type})
}
func (h *CaptchaHandler) Get(c *gin.Context) {
if !h.config.Enabled {
if !h.service.GetConfig().Enabled {
resp.ERROR(c, "验证码服务未启用")
return
}
@@ -56,7 +58,7 @@ func (h *CaptchaHandler) Get(c *gin.Context) {
// Check verify the captcha data
func (h *CaptchaHandler) Check(c *gin.Context) {
if !h.config.Enabled {
if !h.service.GetConfig().Enabled {
resp.ERROR(c, "验证码服务未启用")
return
}
@@ -80,7 +82,7 @@ func (h *CaptchaHandler) Check(c *gin.Context) {
// SlideGet 获取滑动验证图片
func (h *CaptchaHandler) SlideGet(c *gin.Context) {
if !h.config.Enabled {
if !h.service.GetConfig().Enabled {
resp.ERROR(c, "验证码服务未启用")
return
}
@@ -96,7 +98,7 @@ func (h *CaptchaHandler) SlideGet(c *gin.Context) {
// SlideCheck 滑动验证结果校验
func (h *CaptchaHandler) SlideCheck(c *gin.Context) {
if !h.config.Enabled {
if !h.service.GetConfig().Enabled {
resp.ERROR(c, "验证码服务未启用")
return
}

View File

@@ -9,7 +9,6 @@ package handler
import (
"geekai/core"
"geekai/core/middleware"
"geekai/store/model"
"geekai/store/vo"
"geekai/utils"
@@ -30,12 +29,7 @@ func NewChatModelHandler(app *core.AppServer, db *gorm.DB) *ChatModelHandler {
// RegisterRoutes 注册路由
func (h *ChatModelHandler) RegisterRoutes() {
group := h.App.Engine.Group("/api/model/")
// 需要用户授权的接口
group.Use(middleware.UserAuthMiddleware(h.App.Config.Session.SecretKey, h.App.Redis))
{
group.GET("list", h.List)
}
group.GET("list", h.List)
}
// List 模型列表

View File

@@ -24,10 +24,10 @@ const CodeStorePrefix = "/verify/codes/"
type SmsHandler struct {
BaseHandler
redis *redis.Client
sms *sms.SmsManager
smtp *service.SmtpService
captcha *service.CaptchaService
redis *redis.Client
sms *sms.SmsManager
smtp *service.SmtpService
captchaService *service.CaptchaService
}
func NewSmsHandler(
@@ -37,11 +37,11 @@ func NewSmsHandler(
smtp *service.SmtpService,
captcha *service.CaptchaService) *SmsHandler {
return &SmsHandler{
redis: client,
sms: sms,
captcha: captcha,
smtp: smtp,
BaseHandler: BaseHandler{App: app}}
redis: client,
sms: sms,
captchaService: captcha,
smtp: smtp,
BaseHandler: BaseHandler{App: app}}
}
// RegisterRoutes 注册路由
@@ -63,12 +63,12 @@ func (h *SmsHandler) SendCode(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs)
return
}
if h.App.SysConfig.Base.EnabledVerify {
if h.captchaService.GetConfig().Enabled {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
check = h.captchaService.SlideCheck(data)
} else {
check = h.captcha.Check(data)
check = h.captchaService.Check(data)
}
if !check {
resp.ERROR(c, "请先完人机验证")

View File

@@ -35,7 +35,7 @@ type UserHandler struct {
redis *redis.Client
levelDB *store.LevelDB
licenseService *service.LicenseService
captcha *service.CaptchaService
captchaService *service.CaptchaService
userService *service.UserService
}
@@ -53,7 +53,7 @@ func NewUserHandler(
searcher: searcher,
redis: client,
levelDB: levelDB,
captcha: captcha,
captchaService: captcha,
licenseService: licenseService,
userService: userService,
}
@@ -104,12 +104,13 @@ func (h *UserHandler) Register(c *gin.Context) {
return
}
if h.App.SysConfig.Base.EnabledVerify && data.RegWay == "username" {
// 如果注册方式不是账号密码,则需要验证码
if h.captchaService.GetConfig().Enabled && data.RegWay != "username" {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
check = h.captchaService.SlideCheck(data)
} else {
check = h.captcha.Check(data)
check = h.captchaService.Check(data)
}
if !check {
resp.ERROR(c, "请先完人机验证")
@@ -279,15 +280,12 @@ func (h *UserHandler) Login(c *gin.Context) {
resp.ERROR(c, types.InvalidArgs)
return
}
verifyKey := fmt.Sprintf("users/verify/%s", data.Username)
needVerify, err := h.redis.Get(c, verifyKey).Bool()
if h.App.SysConfig.Base.EnabledVerify && needVerify {
if h.captchaService.GetConfig().Enabled {
var check bool
if data.X != 0 {
check = h.captcha.SlideCheck(data)
check = h.captchaService.SlideCheck(data)
} else {
check = h.captcha.Check(data)
check = h.captchaService.Check(data)
}
if !check {
resp.ERROR(c, "请先完人机验证")
@@ -298,19 +296,17 @@ func (h *UserHandler) Login(c *gin.Context) {
var user model.User
res := h.DB.Where("username = ?", data.Username).First(&user)
if res.Error != nil {
h.redis.Set(c, verifyKey, true, 0)
resp.ERROR(c, "用户名不存在")
return
}
password := utils.GenPassword(data.Password, user.Salt)
if password != user.Password {
h.redis.Set(c, verifyKey, true, 0)
resp.ERROR(c, "用户名或密码错误")
return
}
if user.Status == false {
if !user.Status {
resp.ERROR(c, "该用户已被禁止登录,请联系管理员")
return
}
@@ -343,8 +339,6 @@ func (h *UserHandler) Login(c *gin.Context) {
resp.ERROR(c, "error with save token: "+err.Error())
return
}
// 移除登录行为验证码
h.redis.Del(c, verifyKey)
resp.SUCCESS(c, gin.H{"token": tokenString, "user_id": user.Id, "username": user.Username})
}

View File

@@ -31,6 +31,10 @@ func (s *CaptchaService) UpdateConfig(config types.CaptchaConfig) {
s.config = config
}
func (s *CaptchaService) GetConfig() types.CaptchaConfig {
return s.config
}
func (s *CaptchaService) Get() (interface{}, error) {
url := fmt.Sprintf("%s/api/captcha/get", types.GeekAPIURL)
var res types.BizVo
@@ -48,7 +52,7 @@ func (s *CaptchaService) Get() (interface{}, error) {
return res.Data, nil
}
func (s *CaptchaService) Check(data interface{}) bool {
func (s *CaptchaService) Check(data any) bool {
url := fmt.Sprintf("%s/api/captcha/check", types.GeekAPIURL)
var res types.BizVo
r, err := s.client.R().
@@ -66,7 +70,7 @@ func (s *CaptchaService) Check(data interface{}) bool {
return true
}
func (s *CaptchaService) SlideGet() (interface{}, error) {
func (s *CaptchaService) SlideGet() (any, error) {
url := fmt.Sprintf("%s/api/captcha/slide/get", types.GeekAPIURL)
var res types.BizVo
r, err := s.client.R().
@@ -83,7 +87,7 @@ func (s *CaptchaService) SlideGet() (interface{}, error) {
return res.Data, nil
}
func (s *CaptchaService) SlideCheck(data interface{}) bool {
func (s *CaptchaService) SlideCheck(data any) bool {
url := fmt.Sprintf("%s/api/captcha/slide/check", types.GeekAPIURL)
var res types.BizVo
r, err := s.client.R().