Files
backend/.qoder/repowiki/zh/content/配置管理/JWT配置.md
lan a4b6c5011e
Some checks failed
SonarQube Analysis / sonarqube (push) Has been cancelled
chore(git): 更新.gitignore以忽略新的本地文件
2025-11-30 08:33:17 +08:00

331 lines
12 KiB
Markdown
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.

# JWT配置
<cite>
**本文引用的文件**
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go)
- [pkg/auth/manager.go](file://pkg/auth/manager.go)
- [pkg/config/config.go](file://pkg/config/config.go)
- [pkg/config/manager.go](file://pkg/config/manager.go)
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go)
- [internal/service/user_service.go](file://internal/service/user_service.go)
- [scripts/check-env.sh](file://scripts/check-env.sh)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件聚焦于CarrotSkin项目的JWT认证令牌配置系统性说明以下内容
- jwt.secret与expire_hours两个核心配置项的作用与默认值
- 如何通过环境变量JWT_SECRET与JWT_EXPIRE_HOURS进行安全覆盖
- 基于JWTConfig结构体与认证服务代码的安全最佳实践
- 密钥生成建议与有效期设置策略
## 项目结构
围绕JWT配置的相关文件分布如下
- 配置加载与默认值pkg/config/config.go、pkg/config/manager.go
- JWT服务与管理器pkg/auth/jwt.go、pkg/auth/manager.go
- 认证处理器与服务层集成internal/handler/auth_handler.go、internal/service/user_service.go
- 环境变量检查脚本scripts/check-env.sh
```mermaid
graph TB
subgraph "配置层"
CFG["pkg/config/config.go<br/>加载与默认值"]
CMGR["pkg/config/manager.go<br/>配置单例管理"]
end
subgraph "认证层"
JCFG["pkg/auth/jwt.go<br/>JWT服务与声明"]
JMGR["pkg/auth/manager.go<br/>JWT服务单例管理"]
end
subgraph "业务层"
AH["internal/handler/auth_handler.go<br/>登录/注册接口"]
US["internal/service/user_service.go<br/>登录/注册业务"]
end
subgraph "工具"
ENV["scripts/check-env.sh<br/>环境变量检查"]
end
CFG --> CMGR
CMGR --> JMGR
JCFG --> JMGR
AH --> US
AH --> JMGR
US --> JCFG
ENV --> CFG
```
图表来源
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
- [pkg/config/manager.go](file://pkg/config/manager.go#L19-L46)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L10-L71)
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L41)
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
- [scripts/check-env.sh](file://scripts/check-env.sh#L1-L78)
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
- [pkg/config/manager.go](file://pkg/config/manager.go#L19-L46)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L10-L71)
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L41)
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
- [scripts/check-env.sh](file://scripts/check-env.sh#L1-L78)
## 核心组件
- JWTConfig结构体
- 字段Secret密钥、ExpireHours过期小时数
- 默认值ExpireHours默认168小时7天
- 环境变量映射JWT_SECRET、JWT_EXPIRE_HOURS
- JWTService
- 作用生成与验证JWT令牌声明包含用户ID、用户名、角色及标准声明签发时间、过期时间等
- 过期时间由expireHours决定默认168小时
- JWT服务管理器
- 提供Init(cfg)一次性初始化GetJWTService()/MustGetJWTService()获取全局实例
- 认证服务集成
- 登录/注册成功后通过JWTService生成令牌并返回给客户端
- 环境变量检查
- 脚本会校验JWT_SECRET长度与默认值提示
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L67-L71)
- [pkg/config/config.go](file://pkg/config/config.go#L163-L165)
- [pkg/config/config.go](file://pkg/config/config.go#L220-L223)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L10-L71)
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L41)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
- [scripts/check-env.sh](file://scripts/check-env.sh#L58-L77)
## 架构总览
下图展示JWT配置从环境变量到服务使用的端到端流程。
```mermaid
sequenceDiagram
participant ENV as "环境变量"
participant CFG as "配置加载(config.Load)"
participant CMGR as "配置管理器(config.Init)"
participant JMGR as "JWT管理器(auth.Init)"
participant Jsvc as "JWT服务(auth.JWTService)"
participant H as "认证处理器(handler.Login/Register)"
participant S as "业务服务(service.LoginUser/RegisterUser)"
ENV-->>CFG : "JWT_SECRET/JWT_EXPIRE_HOURS"
CFG-->>CMGR : "加载并解析配置(Config)"
CMGR-->>JMGR : "传入JWTConfig(Secret, ExpireHours)"
JMGR-->>Jsvc : "创建JWTService实例"
H->>S : "调用登录/注册业务"
S->>Jsvc : "生成JWT令牌"
Jsvc-->>S : "返回token"
S-->>H : "返回token与用户信息"
H-->>Client : "HTTP响应(含token)"
```
图表来源
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
- [pkg/config/manager.go](file://pkg/config/manager.go#L19-L46)
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L23)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L32-L53)
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
## 详细组件分析
### JWTConfig与默认值
- 结构体定义
- Secret字符串用于签名与验证JWT
- ExpireHours整数令牌有效期小时默认1687天
- 默认值来源
- 通过Viper设置默认值确保未提供环境变量时仍能运行
- 环境变量映射
- JWT_SECRET → jwt.secret
- JWT_EXPIRE_HOURS → jwt.expire_hours
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L67-L71)
- [pkg/config/config.go](file://pkg/config/config.go#L163-L165)
- [pkg/config/config.go](file://pkg/config/config.go#L220-L223)
### JWTService与Claims
- JWTService
- 字段secretKey、expireHours
- 方法GenerateToken、ValidateToken
- Claims
- 包含用户ID、用户名、角色以及标准声明签发时间、过期时间、生效时间、发行者等
- 令牌生成
- 使用HS256算法签名过期时间基于expireHours计算
- 令牌验证
- 使用同一secretKey进行验证若签名不符或过期则报错
```mermaid
classDiagram
class JWTService {
-string secretKey
-int expireHours
+GenerateToken(userID, username, role) string,error
+ValidateToken(tokenString) Claims,error
}
class Claims {
+int64 UserID
+string Username
+string Role
+RegisteredClaims
}
JWTService --> Claims : "生成/验证"
```
图表来源
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L10-L71)
章节来源
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L10-L71)
### JWT服务管理器
- Init(cfg)
- 仅初始化一次使用sync.Once保证幂等
- 将cfg中的Secret与ExpireHours注入JWTService
- GetJWTService/MustGetJWTService
- 提供全局唯一实例访问未初始化时报错或panic
```mermaid
flowchart TD
Start(["调用 auth.Init(cfg)"]) --> Once{"是否已初始化?"}
Once --> |否| Create["创建JWTService实例<br/>注入Secret/ExpireHours"]
Once --> |是| Skip["跳过初始化"]
Create --> Done(["完成"])
Skip --> Done
```
图表来源
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L23)
章节来源
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L41)
### 认证服务与JWT集成
- 登录/注册成功后业务层调用JWTService生成令牌
- 处理器层接收令牌并返回给客户端
```mermaid
sequenceDiagram
participant C as "客户端"
participant H as "Handler(Login/Register)"
participant S as "Service(LoginUser/RegisterUser)"
participant J as "JWTService"
C->>H : "POST /api/v1/auth/login"
H->>S : "LoginUser(jwtService, ...)"
S->>J : "GenerateToken(userID, username, role)"
J-->>S : "token"
S-->>H : "user + token"
H-->>C : "200 OK + token"
```
图表来源
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L32-L53)
章节来源
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L32-L53)
### 环境变量覆盖与安全检查
- 环境变量映射
- JWT_SECRET → jwt.secret
- JWT_EXPIRE_HOURS → jwt.expire_hours
- 默认值
- ExpireHours默认1687天
- 安全检查
- 脚本会检查JWT_SECRET长度是否小于32字符并提示使用默认密钥的风险
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L220-L223)
- [pkg/config/config.go](file://pkg/config/config.go#L163-L165)
- [scripts/check-env.sh](file://scripts/check-env.sh#L58-L77)
## 依赖关系分析
- 配置层
- config.Load负责从.env与环境变量加载配置设置默认值并映射JWT相关键
- config.Init提供全局配置单例
- 认证层
- auth.Init接收JWTConfig创建JWTService实例
- auth.GetJWTService/MustGetJWTService提供全局访问
- 业务层
- handler.Login/Register通过MustGetJWTService获取JWTService
- service.LoginUser/RegisterUser调用JWTService生成令牌
```mermaid
graph LR
CFG["config.Load"] --> CMGR["config.Init/GetConfig"]
CMGR --> JMGR["auth.Init"]
JMGR --> Jsvc["auth.JWTService"]
AH["handler.Login/Register"] --> Jsvc
US["service.LoginUser/RegisterUser"] --> Jsvc
```
图表来源
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
- [pkg/config/manager.go](file://pkg/config/manager.go#L19-L46)
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L23)
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
章节来源
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
- [pkg/config/manager.go](file://pkg/config/manager.go#L19-L46)
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L18-L23)
- [internal/handler/auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
- [internal/service/user_service.go](file://internal/service/user_service.go#L55-L107)
## 性能考量
- 令牌生成与验证均为内存操作,开销极低
- 过期时间越长,客户端缓存令牌的时间越久,减少鉴权次数;但会增加泄露风险
- 建议在移动端或易泄露设备上缩短expire_hours在可信环境适当延长
## 故障排查指南
- JWT服务未初始化
- 现象调用GetJWTService/MustGetJWTService时报错或panic
- 排查确认已在应用启动阶段调用auth.Init(cfg)
- 令牌无效
- 现象ValidateToken返回错误
- 排查确认使用相同的JWT_SECRET检查网络传输是否篡改核对过期时间
- 环境变量未生效
- 现象JWT_EXPIRE_HOURS未按预期
- 排查:确认环境变量名正确且已导出;检查.env文件路径与加载顺序
章节来源
- [pkg/auth/manager.go](file://pkg/auth/manager.go#L26-L41)
- [pkg/auth/jwt.go](file://pkg/auth/jwt.go#L55-L71)
- [pkg/config/config.go](file://pkg/config/config.go#L108-L133)
## 结论
- jwt.secret用于签名与验证JWT必须保密且足够随机
- expire_hours控制令牌有效期默认168小时7天可通过JWT_EXPIRE_HOURS覆盖
- 通过JWT_SECRET与JWT_EXPIRE_HOURS实现安全可控的令牌策略
- 建议在生产环境使用长随机密钥,并根据业务场景调整有效期
## 附录
### 安全最佳实践
- 密钥生成建议
- 使用足够长度的随机字符串作为JWT_SECRET建议≥32字符
- 避免使用默认密钥或弱口令
- 有效期设置策略
- 移动端/公共设备较短有效期如24-72小时
- 可信服务间可适当延长如7天
- 环境变量管理
- 在部署时通过环境变量覆盖,避免硬编码
- 使用脚本检查密钥长度与默认值风险
章节来源
- [scripts/check-env.sh](file://scripts/check-env.sh#L58-L77)
- [pkg/config/config.go](file://pkg/config/config.go#L163-L165)
- [pkg/config/config.go](file://pkg/config/config.go#L220-L223)