chore(git): 更新.gitignore以忽略新的本地文件
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
This commit is contained in:
351
.qoder/repowiki/zh/content/API参考/认证API/用户登录.md
Normal file
351
.qoder/repowiki/zh/content/API参考/认证API/用户登录.md
Normal file
@@ -0,0 +1,351 @@
|
||||
# 用户登录
|
||||
|
||||
<cite>
|
||||
**本文引用的文件**
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [routes.go](file://internal/handler/routes.go)
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [password.go](file://pkg/auth/password.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [common.go](file://internal/types/common.go)
|
||||
- [response.go](file://internal/model/response.go)
|
||||
- [user.go](file://internal/model/user.go)
|
||||
- [token.go](file://internal/model/token.go)
|
||||
- [token_service.go](file://internal/service/token_service.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构总览](#架构总览)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖关系分析](#依赖关系分析)
|
||||
7. [性能考量](#性能考量)
|
||||
8. [故障排查指南](#故障排查指南)
|
||||
9. [结论](#结论)
|
||||
10. [附录](#附录)
|
||||
|
||||
## 简介
|
||||
本文件面向“用户登录”API,围绕 /api/v1/auth/login 端点进行完整说明,覆盖:
|
||||
- HTTP 方法与路由
|
||||
- 请求体结构(用户名或邮箱登录)
|
||||
- 响应格式(包含JWT token与用户信息)
|
||||
- 错误码与错误处理
|
||||
- JWT令牌生成流程(访问令牌与声明)
|
||||
- 登录成功/失败后的审计日志记录(IP、User-Agent)
|
||||
- 安全建议(防暴力破解、错误提示模糊化)
|
||||
|
||||
## 项目结构
|
||||
该登录流程涉及以下模块协作:
|
||||
- 路由层:注册 /api/v1/auth/login 路由
|
||||
- 控制器层:处理登录请求、参数校验、调用服务层
|
||||
- 服务层:用户查找、密码校验、令牌生成、登录日志记录
|
||||
- 认证与密码:JWT服务、bcrypt密码加解密
|
||||
- 数据模型:用户、登录日志、令牌
|
||||
- 中间件:JWT认证中间件用于后续受保护接口
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Client["客户端"] --> Routes["路由注册<br/>/api/v1/auth/login"]
|
||||
Routes --> Handler["控制器 Login()<br/>参数绑定/错误处理"]
|
||||
Handler --> Service["服务层 LoginUser()<br/>查找用户/校验密码/生成JWT"]
|
||||
Service --> JWT["JWT服务 GenerateToken()<br/>签发访问令牌"]
|
||||
Service --> ModelUser["用户模型 User"]
|
||||
Service --> ModelLog["登录日志 UserLoginLog"]
|
||||
Handler --> Resp["统一响应 Response/ErrorResponse"]
|
||||
Client --> Middleware["认证中间件 AuthMiddleware()<br/>Bearer Token 校验"]
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L25)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [user.go](file://internal/model/user.go#L1-L21)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
||||
|
||||
章节来源
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L25)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
|
||||
## 核心组件
|
||||
- 路由与控制器
|
||||
- /api/v1/auth/login 由控制器 Login 处理,负责参数绑定、IP/User-Agent采集、调用服务层并返回统一响应。
|
||||
- 服务层
|
||||
- LoginUser 支持用户名或邮箱登录;校验用户状态与密码;生成JWT;更新最后登录时间;记录成功/失败日志。
|
||||
- 认证与密码
|
||||
- JWT服务提供 GenerateToken/ValidateToken;密码使用 bcrypt 进行哈希与校验。
|
||||
- 数据模型
|
||||
- User:用户信息;UserLoginLog:登录审计日志;Token:令牌模型(用于后续刷新/失效等场景)。
|
||||
- 统一响应
|
||||
- Response/ErrorResponse 提供统一的状态码与消息封装。
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [password.go](file://pkg/auth/password.go#L7-L21)
|
||||
- [user.go](file://internal/model/user.go#L1-L21)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
- [token.go](file://internal/model/token.go#L1-L15)
|
||||
- [response.go](file://internal/model/response.go#L20-L53)
|
||||
|
||||
## 架构总览
|
||||
登录端到端序列图(POST /api/v1/auth/login):
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as "客户端"
|
||||
participant R as "路由"
|
||||
participant H as "控制器 Login()"
|
||||
participant S as "服务层 LoginUser()"
|
||||
participant J as "JWT服务"
|
||||
participant U as "用户模型"
|
||||
participant L as "登录日志"
|
||||
C->>R : "POST /api/v1/auth/login"
|
||||
R->>H : "进入 Login 控制器"
|
||||
H->>H : "ShouldBindJSON 绑定请求体"
|
||||
H->>S : "LoginUser(jwtService, username, password, ip, ua)"
|
||||
S->>U : "根据用户名或邮箱查找用户"
|
||||
S->>S : "校验用户状态"
|
||||
S->>S : "bcrypt 校验密码"
|
||||
S->>J : "GenerateToken(userID, username, role)"
|
||||
J-->>S : "返回JWT字符串"
|
||||
S->>U : "更新 last_login_at"
|
||||
S->>L : "logSuccessLogin/logFailedLogin"
|
||||
S-->>H : "返回 user, token"
|
||||
H-->>C : "200 成功响应或401失败响应"
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [user.go](file://internal/model/user.go#L1-L21)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### 接口定义与请求/响应
|
||||
- HTTP 方法与路径
|
||||
- 方法:POST
|
||||
- 路径:/api/v1/auth/login
|
||||
- 请求体结构
|
||||
- 字段:username(支持用户名或邮箱)、password(6-128字符)
|
||||
- 参数校验:必填、长度约束
|
||||
- 响应格式
|
||||
- 成功:统一响应,data 包含 token 与 userInfo
|
||||
- 失败:统一错误响应,包含 code 与 message
|
||||
- 错误码
|
||||
- 400:请求参数错误
|
||||
- 401:未授权(用户名/邮箱或密码错误、账号被禁用等)
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [common.go](file://internal/types/common.go#L27-L31)
|
||||
- [response.go](file://internal/model/response.go#L20-L53)
|
||||
|
||||
### 请求体结构与参数校验
|
||||
- 请求体字段
|
||||
- username:支持用户名或邮箱
|
||||
- password:6-128字符
|
||||
- 参数校验
|
||||
- Gin 绑定时会触发结构体 tag 校验(必填、长度范围)
|
||||
- 实际行为
|
||||
- 控制器层在绑定失败时直接返回400
|
||||
|
||||
章节来源
|
||||
- [common.go](file://internal/types/common.go#L27-L31)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L101-L109)
|
||||
|
||||
### 登录流程与JWT生成
|
||||
- 登录流程要点
|
||||
- 识别登录方式:包含@视为邮箱,否则为用户名
|
||||
- 校验用户状态(仅状态为正常才允许登录)
|
||||
- 使用 bcrypt 校验密码
|
||||
- 生成JWT访问令牌(包含用户ID、用户名、角色等声明)
|
||||
- 更新最后登录时间
|
||||
- 记录登录日志(成功/失败均记录IP与User-Agent)
|
||||
- JWT声明内容
|
||||
- 包含 user_id、username、role
|
||||
- 默认包含过期时间、签发时间、生效时间、签发者等注册声明
|
||||
- 令牌有效期
|
||||
- 由JWT服务配置的过期小时数决定
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start(["进入 LoginUser"]) --> Detect["判断登录方式<br/>用户名或邮箱"]
|
||||
Detect --> FindUser["查找用户"]
|
||||
FindUser --> Status{"用户状态正常?"}
|
||||
Status -- 否 --> LogFail["记录失败日志<br/>原因:账号被禁用"]
|
||||
LogFail --> ReturnErr["返回错误"]
|
||||
Status -- 是 --> CheckPwd["bcrypt 校验密码"]
|
||||
CheckPwd --> PwdOK{"密码正确?"}
|
||||
PwdOK -- 否 --> LogFail2["记录失败日志<br/>原因:密码错误"]
|
||||
LogFail2 --> ReturnErr
|
||||
PwdOK -- 是 --> GenToken["GenerateToken(userID, username, role)"]
|
||||
GenToken --> UpdateTime["更新 last_login_at"]
|
||||
UpdateTime --> LogSuccess["记录成功日志"]
|
||||
LogSuccess --> Done(["返回 user, token"])
|
||||
ReturnErr --> Done
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [password.go](file://pkg/auth/password.go#L16-L21)
|
||||
- [user.go](file://internal/model/user.go#L1-L21)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
|
||||
章节来源
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [password.go](file://pkg/auth/password.go#L16-L21)
|
||||
|
||||
### 响应格式与错误码
|
||||
- 成功响应
|
||||
- data:包含 token 与 userInfo(id、username、email、avatar、points、role、status、last_login_at、created_at、updated_at)
|
||||
- 失败响应
|
||||
- 400:请求参数错误
|
||||
- 401:未授权(用户名/邮箱或密码错误、账号被禁用)
|
||||
- 统一响应封装
|
||||
- Response/ErrorResponse 提供 code、message、data/error 字段
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L131-L147)
|
||||
- [common.go](file://internal/types/common.go#L107-L126)
|
||||
- [response.go](file://internal/model/response.go#L20-L53)
|
||||
|
||||
### 登录日志记录(IP、User-Agent)
|
||||
- 记录内容
|
||||
- 成功/失败均记录:用户ID、IP地址、User-Agent、登录方式(PASSWORD)、是否成功、失败原因
|
||||
- 记录时机
|
||||
- 成功:登录成功后记录
|
||||
- 失败:用户不存在、账号禁用、密码错误等情况下记录
|
||||
- 存储位置
|
||||
- 写入 user_login_logs 表
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L111-L129)
|
||||
- [user_service.go](file://internal/service/user_service.go#L203-L226)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
|
||||
### 安全考虑与建议
|
||||
- 防暴力破解
|
||||
- 建议在网关或应用层增加速率限制(例如基于IP或用户名的限流),在失败时延长冷却时间或临时封禁
|
||||
- 可结合验证码机制(当前登录接口未强制验证码,但注册/重置密码有验证码流程)
|
||||
- 错误提示模糊化
|
||||
- 当前服务层对“用户不存在/密码错误/账号禁用”均返回统一的“用户名/邮箱或密码错误”,避免泄露具体原因
|
||||
- 令牌管理
|
||||
- 当前登录仅返回JWT访问令牌;若需刷新令牌,可参考后续令牌服务(刷新/失效等)能力
|
||||
- 传输安全
|
||||
- 建议仅在HTTPS下提供登录接口,防止凭据被窃听
|
||||
|
||||
章节来源
|
||||
- [user_service.go](file://internal/service/user_service.go#L88-L103)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L116-L129)
|
||||
|
||||
## 依赖关系分析
|
||||
- 控制器依赖
|
||||
- 控制器 Login 依赖:JWT服务、日志、Redis(注册流程)、服务层 LoginUser
|
||||
- 服务层依赖
|
||||
- LoginUser 依赖:用户仓库(查找用户)、JWT服务(生成令牌)、密码工具(bcrypt)、登录日志仓库(写入日志)
|
||||
- 认证依赖
|
||||
- JWT服务依赖:golang-jwt库;密码工具依赖:bcrypt
|
||||
- 模型依赖
|
||||
- User、UserLoginLog、Token 模型用于数据持久化与审计
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
H["控制器 Login()"] --> S["服务层 LoginUser()"]
|
||||
H --> J["JWT服务 GenerateToken()"]
|
||||
S --> U["User 模型"]
|
||||
S --> L["UserLoginLog 模型"]
|
||||
S --> P["bcrypt 密码校验"]
|
||||
H --> R["路由 RegisterRoutes()"]
|
||||
M["认证中间件 AuthMiddleware()"] --> J
|
||||
```
|
||||
|
||||
图表来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [password.go](file://pkg/auth/password.go#L16-L21)
|
||||
- [user.go](file://internal/model/user.go#L1-L21)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L25)
|
||||
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L70-L122)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L53)
|
||||
- [password.go](file://pkg/auth/password.go#L16-L21)
|
||||
- [user.go](file://internal/model/user.go#L1-L21)
|
||||
- [user.go](file://internal/model/user.go#L52-L71)
|
||||
- [routes.go](file://internal/handler/routes.go#L16-L25)
|
||||
- [auth.go](file://internal/middleware/auth.go#L12-L56)
|
||||
|
||||
## 性能考量
|
||||
- 登录路径涉及数据库查询与密码校验,建议:
|
||||
- 对用户表建立合适的索引(username、email)
|
||||
- 密码校验使用 bcrypt,默认成本适中,可根据硬件能力调整
|
||||
- 登录日志写入采用异步或批量策略(当前为同步写入,注意高并发下的I/O影响)
|
||||
- JWT生成与校验为CPU密集度较低的操作,主要瓶颈在数据库与密码校验
|
||||
|
||||
## 故障排查指南
|
||||
- 常见问题与定位
|
||||
- 400 参数错误:检查请求体字段是否缺失或长度不符合要求
|
||||
- 401 未授权:核对用户名/邮箱是否存在、账号状态是否正常、密码是否正确
|
||||
- 登录日志未记录:确认日志写入是否成功,检查数据库连接与表结构
|
||||
- 日志与审计
|
||||
- 成功/失败日志均包含 IP 与 User-Agent,便于追踪来源设备与来源网络
|
||||
- 令牌相关
|
||||
- 若后续引入刷新令牌,可参考令牌服务中的刷新/失效逻辑
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L101-L129)
|
||||
- [user_service.go](file://internal/service/user_service.go#L203-L226)
|
||||
- [response.go](file://internal/model/response.go#L20-L53)
|
||||
|
||||
## 结论
|
||||
/api/v1/auth/login 提供了完整的用户名或邮箱登录能力,具备参数校验、密码校验、JWT签发与登录日志记录。当前实现聚焦于登录流程本身,后续可在速率限制、验证码、刷新令牌等方面进一步增强安全性与可用性。
|
||||
|
||||
## 附录
|
||||
|
||||
### API定义与示例
|
||||
|
||||
- 端点
|
||||
- 方法:POST
|
||||
- 路径:/api/v1/auth/login
|
||||
- 请求体
|
||||
- username:字符串,必填,支持用户名或邮箱
|
||||
- password:字符串,必填,长度6-128
|
||||
- 成功响应
|
||||
- code:200
|
||||
- data:包含 token 与 userInfo
|
||||
- 示例(结构示意)
|
||||
- data: { token: "...", userInfo: { id, username, email, avatar, points, role, status, last_login_at, created_at, updated_at } }
|
||||
- 失败响应
|
||||
- 400:请求参数错误
|
||||
- 401:未授权(用户名/邮箱或密码错误、账号被禁用)
|
||||
|
||||
章节来源
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L86-L147)
|
||||
- [common.go](file://internal/types/common.go#L27-L31)
|
||||
- [common.go](file://internal/types/common.go#L107-L126)
|
||||
- [response.go](file://internal/model/response.go#L20-L53)
|
||||
|
||||
### JWT声明与令牌生命周期
|
||||
- 声明内容
|
||||
- user_id、username、role
|
||||
- 过期时间、签发时间、生效时间、签发者等注册声明
|
||||
- 令牌类型
|
||||
- 当前登录返回访问令牌;刷新/失效等能力可参考令牌服务
|
||||
|
||||
章节来源
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L24-L53)
|
||||
- [token_service.go](file://internal/service/token_service.go#L151-L238)
|
||||
Reference in New Issue
Block a user