250 lines
6.5 KiB
Go
250 lines
6.5 KiB
Go
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()
|
||
}
|