feat(auth): 完整认证系统 — 注册/登录/JWT/路由(Task 4 + Task 5)

Task 4 — 认证服务层:
- pkg/utils/password.go: bcrypt 密码加密与校验
- pkg/utils/jwt.go: Access/Refresh Token 生成与解析(jwt/v5@v5.2.1,兼容 Go 1.23)
- app/dto/auth_dto.go: 认证相关请求/响应 DTO(含参数校验 binding tag)
- app/auth/service/auth_service.go: 核心业务逻辑(注册、登录、管理员登录、Token 刷新、个人信息、改密码)
- pkg/middleware/auth.go: JWT 认证中间件 + 角色权限检查中间件

Task 5 — Controller 与路由注册:
- app/auth/controller/auth_controller.go: 前台认证接口(7 个 API)
- app/auth/controller/admin_auth_controller.go: 后台管理认证接口
- app/auth/router.go: auth 模块路由定义(模块自包含)
- router/router.go: 主路由汇总入口(仅做调度,不含具体路由定义)
- cmd/server/main.go: 路由注册迁移到 router.Setup()

已验证全部接口:注册 ✓ 登录 ✓ 获取 profile ✓ 错误密码 ✓ 未认证拒绝 ✓ 非管理员拒绝 ✓

Made-with: Cursor
This commit is contained in:
bujinyuan
2026-02-28 16:42:28 +08:00
parent 4d3d486902
commit d975adaf2a
18 changed files with 1097 additions and 41 deletions

View File

@@ -0,0 +1,54 @@
// Package dto 定义数据传输对象,用于 Controller 层的请求/响应参数绑定
package dto
// RegisterRequest 用户注册请求参数
type RegisterRequest struct {
Username string `json:"username" binding:"required,min=3,max=50"` // 用户名3-50 字符
Email string `json:"email" binding:"required,email"` // 邮箱地址,必须符合邮箱格式
Password string `json:"password" binding:"required,min=6,max=50"` // 密码6-50 字符
Nickname string `json:"nickname" binding:"max=50"` // 昵称,可选,最多 50 字符
}
// LoginRequest 用户登录请求参数
type LoginRequest struct {
Account string `json:"account" binding:"required"` // 登录账号,支持用户名或邮箱
Password string `json:"password" binding:"required"` // 登录密码
}
// LoginResponse 登录成功响应数据
type LoginResponse struct {
Token string `json:"token"` // Access Token用于接口认证
RefreshToken string `json:"refresh_token"` // Refresh Token用于刷新 Access Token
ExpiresIn int64 `json:"expires_in"` // Access Token 有效期(秒)
User UserInfo `json:"user"` // 当前登录用户基本信息
}
// UserInfo 用户基本信息(用于响应返回,不含敏感字段)
type UserInfo struct {
ID int64 `json:"id"` // 用户 ID
Username string `json:"username"` // 用户名
Email string `json:"email"` // 邮箱
Nickname string `json:"nickname"` // 昵称
Avatar string `json:"avatar"` // 头像 URL
Gender int `json:"gender"` // 性别0=未知, 1=男, 2=女
Roles []string `json:"roles"` // 角色代码列表
}
// RefreshTokenRequest 刷新 Token 请求参数
type RefreshTokenRequest struct {
RefreshToken string `json:"refresh_token" binding:"required"` // 原 Refresh Token
}
// UpdateProfileRequest 更新个人资料请求参数
type UpdateProfileRequest struct {
Nickname string `json:"nickname" binding:"max=50"` // 新昵称
Avatar string `json:"avatar" binding:"max=500"` // 新头像 URL
Gender *int `json:"gender" binding:"omitempty,oneof=0 1 2"` // 新性别,指针类型区分「未传」和「传 0」
Phone string `json:"phone" binding:"max=20"` // 新手机号
}
// ChangePasswordRequest 修改密码请求参数
type ChangePasswordRequest struct {
OldPassword string `json:"old_password" binding:"required"` // 旧密码
NewPassword string `json:"new_password" binding:"required,min=6,max=50"` // 新密码6-50 字符
}