2025-12-03 11:00:47 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* package api
|
|
|
|
|
|
* 作用:认证相关API处理器
|
|
|
|
|
|
*/
|
|
|
|
|
|
package api
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"xk-websocket-v2/internal/model"
|
|
|
|
|
|
"xk-websocket-v2/internal/service"
|
|
|
|
|
|
"xk-websocket-v2/internal/utils"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/gin-gonic/gin"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* LoginHandler
|
|
|
|
|
|
* 功能:用户登录
|
|
|
|
|
|
* 路径:POST /api/login
|
|
|
|
|
|
*/
|
|
|
|
|
|
func LoginHandler(c *gin.Context) {
|
|
|
|
|
|
var req model.LoginReq
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
utils.BadRequest(c, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取客户端IP
|
2026-07-08 08:18:58 +08:00
|
|
|
|
ip := utils.GetClientIP(c)
|
2025-12-03 11:00:47 +08:00
|
|
|
|
|
|
|
|
|
|
// 调用认证服务登录
|
|
|
|
|
|
user, err := service.AuthSvc.Login(req.Account, req.Password)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
// 记录登录失败日志
|
|
|
|
|
|
service.LoginLogSvc.LogLogin(req.Account, "0", ip, false)
|
|
|
|
|
|
utils.Unauthorized(c, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成Token
|
|
|
|
|
|
token, err := utils.GenerateToken(user.ID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
// 记录登录失败日志
|
|
|
|
|
|
service.LoginLogSvc.LogLogin(req.Account, "0", ip, false)
|
|
|
|
|
|
utils.InternalError(c, "生成Token失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 清除密码字段
|
|
|
|
|
|
user.Password = ""
|
|
|
|
|
|
|
|
|
|
|
|
// 记录登录成功日志
|
|
|
|
|
|
service.LoginLogSvc.LogLogin(req.Account, user.ID, ip, true)
|
|
|
|
|
|
|
|
|
|
|
|
utils.SuccessWithData(c, model.LoginResponse{
|
|
|
|
|
|
Token: token,
|
|
|
|
|
|
User: *user,
|
|
|
|
|
|
}, "登录成功")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* RegisterHandler
|
|
|
|
|
|
* 功能:用户注册
|
|
|
|
|
|
* 路径:POST /api/register
|
|
|
|
|
|
*/
|
|
|
|
|
|
func RegisterHandler(c *gin.Context) {
|
|
|
|
|
|
var req model.RegisterReq
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
utils.BadRequest(c, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 如果提供了验证码,验证验证码
|
|
|
|
|
|
if req.Code != "" {
|
|
|
|
|
|
// 根据邮箱或手机号确定类型
|
|
|
|
|
|
codeType := "email"
|
|
|
|
|
|
if len(req.Phone) > 0 {
|
|
|
|
|
|
codeType = "sms"
|
|
|
|
|
|
}
|
|
|
|
|
|
target := req.Email
|
|
|
|
|
|
if codeType == "sms" {
|
|
|
|
|
|
target = req.Phone
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
valid, err := service.AuthSvc.VerifyCode(target, req.Code, codeType)
|
|
|
|
|
|
if err != nil || !valid {
|
|
|
|
|
|
utils.BadRequest(c, "验证码无效或已过期")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 调用认证服务注册
|
|
|
|
|
|
user, err := service.AuthSvc.Register(&req)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.BadRequest(c, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 生成Token
|
|
|
|
|
|
token, err := utils.GenerateToken(user.ID)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.InternalError(c, "生成Token失败")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
utils.SuccessWithData(c, model.RegisterResponse{
|
|
|
|
|
|
Token: token,
|
|
|
|
|
|
User: *user,
|
|
|
|
|
|
}, "注册成功")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* LogoutHandler
|
|
|
|
|
|
* 功能:用户登出(可选,前端清除token)
|
|
|
|
|
|
* 路径:POST /api/logout
|
|
|
|
|
|
*/
|
|
|
|
|
|
func LogoutHandler(c *gin.Context) {
|
|
|
|
|
|
// 登出主要是前端清除token,后端可以记录日志或清除session
|
|
|
|
|
|
utils.Success(c, "登出成功")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* CheckTokenHandler
|
|
|
|
|
|
* 功能:检查Token有效性
|
|
|
|
|
|
* 路径:GET /api/check-token
|
|
|
|
|
|
*/
|
|
|
|
|
|
func CheckTokenHandler(c *gin.Context) {
|
|
|
|
|
|
token := c.GetHeader("Authorization")
|
|
|
|
|
|
if token == "" {
|
|
|
|
|
|
utils.Unauthorized(c, "缺少Token")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 移除 "Bearer " 前缀(如果存在)
|
|
|
|
|
|
if len(token) > 7 && token[:7] == "Bearer " {
|
|
|
|
|
|
token = token[7:]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
userID, err := utils.ValidateToken(token)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.Unauthorized(c, "Token无效或已过期")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
utils.SuccessWithData(c, gin.H{
|
|
|
|
|
|
"status": "valid",
|
|
|
|
|
|
"user_id": userID,
|
|
|
|
|
|
}, "Token有效")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* SendEmailCodeHandler
|
|
|
|
|
|
* 功能:发送邮箱验证码
|
|
|
|
|
|
* 路径:POST /api/send-email-code
|
|
|
|
|
|
*/
|
|
|
|
|
|
func SendEmailCodeHandler(c *gin.Context) {
|
|
|
|
|
|
var req model.SendCodeReq
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
utils.BadRequest(c, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if req.Type != "email" {
|
|
|
|
|
|
utils.BadRequest(c, "类型必须是email")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
code, err := service.AuthSvc.SendEmailCode(req.Target)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.InternalError(c, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 开发环境返回验证码,生产环境不应返回
|
|
|
|
|
|
utils.SuccessWithData(c, gin.H{
|
|
|
|
|
|
"code": code, // 仅开发环境,生产环境应移除
|
|
|
|
|
|
}, "验证码已发送")
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* SendSmsCodeHandler
|
|
|
|
|
|
* 功能:发送短信验证码
|
|
|
|
|
|
* 路径:POST /api/send-sms-code
|
|
|
|
|
|
*/
|
|
|
|
|
|
func SendSmsCodeHandler(c *gin.Context) {
|
|
|
|
|
|
var req model.SendCodeReq
|
|
|
|
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
|
|
|
|
|
utils.BadRequest(c, "参数错误: "+err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if req.Type != "sms" {
|
|
|
|
|
|
utils.BadRequest(c, "类型必须是sms")
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
code, err := service.AuthSvc.SendSmsCode(req.Target)
|
|
|
|
|
|
if err != nil {
|
|
|
|
|
|
utils.InternalError(c, err.Error())
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 开发环境返回验证码,生产环境不应返回
|
|
|
|
|
|
utils.SuccessWithData(c, gin.H{
|
|
|
|
|
|
"code": code, // 仅开发环境,生产环境应移除
|
|
|
|
|
|
}, "验证码已发送")
|
|
|
|
|
|
}
|