Files
nl-im-service/internal/api/auth_handler.go
2025-12-03 11:00:47 +08:00

226 lines
4.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 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
ip := getClientIP(c)
// 调用认证服务登录
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,
}, "登录成功")
}
// getClientIP 获取客户端IP
func getClientIP(c *gin.Context) string {
// 优先从X-Forwarded-For获取
ip := c.GetHeader("X-Forwarded-For")
if ip != "" {
return ip
}
// 从X-Real-IP获取
ip = c.GetHeader("X-Real-IP")
if ip != "" {
return ip
}
// 从RemoteAddr获取
return c.ClientIP()
}
/**
* 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, // 仅开发环境,生产环境应移除
}, "验证码已发送")
}