# JWT配置
**本文引用的文件**
- [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)
## 目录
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
加载与默认值"]
CMGR["pkg/config/manager.go
配置单例管理"]
end
subgraph "认证层"
JCFG["pkg/auth/jwt.go
JWT服务与声明"]
JMGR["pkg/auth/manager.go
JWT服务单例管理"]
end
subgraph "业务层"
AH["internal/handler/auth_handler.go
登录/注册接口"]
US["internal/service/user_service.go
登录/注册业务"]
end
subgraph "工具"
ENV["scripts/check-env.sh
环境变量检查"]
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:整数,令牌有效期(小时),默认168(7天)
- 默认值来源
- 通过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实例
注入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默认168(7天)
- 安全检查
- 脚本会检查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)