This commit is contained in:
2026-06-02 21:15:13 +08:00
parent 31fc86e878
commit e6b84aad80
12 changed files with 2650 additions and 130 deletions
+249
View File
@@ -0,0 +1,249 @@
package controllers
import (
"encoding/json"
"io"
"strings"
"time"
"server/models"
"server/pkg/jwtutil"
beego "github.com/beego/beego/v2/server/web"
)
// BackendLoginVerifyController 后台登录验证配置
// 对应前端 backend/src/api/sitesettings.js
// - GET /backend/loginVerifyInfos
// - POST /backend/saveloginVerifyInfos
type BackendLoginVerifyController struct {
beego.Controller
}
func (c *BackendLoginVerifyController) backendLoginVerifyClaims() (*jwtutil.Claims, error) {
auth := c.Ctx.Request.Header.Get("Authorization")
if auth == "" {
return nil, errBackendLoginVerify("未登录")
}
parts := strings.SplitN(auth, " ", 2)
if len(parts) != 2 || parts[0] != "Bearer" {
return nil, errBackendLoginVerify("认证信息格式错误")
}
claims, err := jwtutil.ParseToken(parts[1])
if err != nil {
return nil, errBackendLoginVerify("无效的token")
}
if claims.UserType != "backend" {
return nil, errBackendLoginVerify("无权访问")
}
return claims, nil
}
type backendLoginVerifyError string
func (e backendLoginVerifyError) Error() string {
return string(e)
}
func errBackendLoginVerify(msg string) error {
return backendLoginVerifyError(msg)
}
func (c *BackendLoginVerifyController) jsonErr(httpStatus, bizCode int, msg string) {
c.Ctx.Output.SetStatus(httpStatus)
c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg}
_ = c.ServeJSON()
}
type backendLoginVerifyPayload struct {
OpenVerify *bool `json:"openVerify"`
OpenVerifyInt *int8 `json:"openVerify_enabled"`
VerifyModel string `json:"verifyModel"`
UseGeetest string `json:"use_geetest"`
Geetest3ID *string `json:"geetest3ID"`
Geetest3IDSnake *string `json:"geetest3_id"`
Geetest3Key *string `json:"geetest3KEY"`
Geetest3KeySnake *string `json:"geetest3_key"`
Geetest4ID *string `json:"geetest4ID"`
Geetest4IDSnake *string `json:"geetest4_id"`
Geetest4Key *string `json:"geetest4KEY"`
Geetest4KeySnake *string `json:"geetest4_key"`
}
func backendVerifyTypeToModel(v string) string {
switch strings.TrimSpace(v) {
case "captcha":
return "1"
case "sms":
return "2"
case "email":
return "3"
case "geetest3":
return "4"
case "geetest", "geetest4":
return "5"
default:
return "1"
}
}
func backendVerifyModelToType(v string) string {
switch strings.TrimSpace(v) {
case "1":
return "captcha"
case "2":
return "sms"
case "3":
return "email"
case "4":
return "geetest3"
case "5":
return "geetest4"
default:
switch strings.TrimSpace(v) {
case "captcha", "sms", "email", "geetest", "geetest3", "geetest4":
return strings.TrimSpace(v)
default:
return "captcha"
}
}
}
func backendStringPtrValue(primary, fallback *string) string {
if primary != nil {
return *primary
}
if fallback != nil {
return *fallback
}
return ""
}
func backendStringPtrOrNil(primary, fallback *string) *string {
value := strings.TrimSpace(backendStringPtrValue(primary, fallback))
if value == "" {
return nil
}
return &value
}
// GetLoginVerifyInfos GET /backend/loginVerifyInfos
func (c *BackendLoginVerifyController) GetLoginVerifyInfos() {
if _, err := c.backendLoginVerifyClaims(); err != nil {
c.jsonErr(401, 401, err.Error())
return
}
cfg, err := models.GetPlatformLoginVerify()
if err != nil {
c.jsonErr(500, 500, "获取配置失败")
return
}
openVerify := "0"
if cfg.OpenVerifyEnabled == 1 {
openVerify = "1"
}
data := []map[string]string{
{"label": "openVerify", "value": openVerify},
{"label": "verifyModel", "value": backendVerifyTypeToModel(cfg.VerifyType)},
{"label": "geetest3ID", "value": backendStringPtrValue(cfg.Geetest3ID, nil)},
{"label": "geetest3KEY", "value": backendStringPtrValue(cfg.Geetest3Key, nil)},
{"label": "geetest4ID", "value": backendStringPtrValue(cfg.Geetest4ID, nil)},
{"label": "geetest4KEY", "value": backendStringPtrValue(cfg.Geetest4Key, nil)},
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": data}
_ = c.ServeJSON()
}
// SaveLoginVerifyInfos POST /backend/saveloginVerifyInfos
func (c *BackendLoginVerifyController) SaveLoginVerifyInfos() {
if _, err := c.backendLoginVerifyClaims(); err != nil {
c.jsonErr(401, 401, err.Error())
return
}
raw, err := io.ReadAll(c.Ctx.Request.Body)
if err != nil {
c.jsonErr(400, 400, "参数错误")
return
}
var p backendLoginVerifyPayload
if err := json.Unmarshal(raw, &p); err != nil {
c.jsonErr(400, 400, "参数错误")
return
}
openVerifyEnabled := int8(0)
if p.OpenVerify != nil && *p.OpenVerify {
openVerifyEnabled = 1
}
if p.OpenVerifyInt != nil {
openVerifyEnabled = *p.OpenVerifyInt
}
verifyModel := p.VerifyModel
if strings.TrimSpace(verifyModel) == "" {
verifyModel = p.UseGeetest
}
verifyType := backendVerifyModelToType(verifyModel)
geetest3ID := backendStringPtrOrNil(p.Geetest3ID, p.Geetest3IDSnake)
geetest3Key := backendStringPtrOrNil(p.Geetest3Key, p.Geetest3KeySnake)
geetest4ID := backendStringPtrOrNil(p.Geetest4ID, p.Geetest4IDSnake)
geetest4Key := backendStringPtrOrNil(p.Geetest4Key, p.Geetest4KeySnake)
if verifyType == "geetest3" {
if geetest3ID == nil || geetest3Key == nil {
c.jsonErr(400, 400, "极验3.0 ID和KEY不能为空")
return
}
}
if verifyType == "geetest4" || verifyType == "geetest" {
if geetest4ID == nil || geetest4Key == nil {
c.jsonErr(400, 400, "极验4.0 ID和KEY不能为空")
return
}
}
now := time.Now()
var existed models.PlatformLoginVerify
err = models.Orm.QueryTable(new(models.PlatformLoginVerify)).OrderBy("-id").One(&existed)
if err == nil {
_, err = models.Orm.QueryTable(new(models.PlatformLoginVerify)).
Filter("id", existed.ID).
Update(map[string]interface{}{
"open_verify_enabled": openVerifyEnabled,
"verify_type": verifyType,
"geetest3_id": geetest3ID,
"geetest3_key": geetest3Key,
"geetest4_id": geetest4ID,
"geetest4_key": geetest4Key,
"update_time": now,
})
if err != nil {
c.jsonErr(500, 500, "保存失败")
return
}
} else {
row := &models.PlatformLoginVerify{
OpenVerifyEnabled: openVerifyEnabled,
VerifyType: verifyType,
Geetest3ID: geetest3ID,
Geetest3Key: geetest3Key,
Geetest4ID: geetest4ID,
Geetest4Key: geetest4Key,
UpdateTime: &now,
}
if _, err := models.Orm.Insert(row); err != nil {
c.jsonErr(500, 500, "保存失败")
return
}
}
c.Data["json"] = map[string]interface{}{"code": 200, "msg": "保存成功"}
_ = c.ServeJSON()
}