12 KiB
12 KiB
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)目录
简介
本文件聚焦于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
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
- pkg/config/manager.go
- pkg/auth/jwt.go
- pkg/auth/manager.go
- internal/handler/auth_handler.go
- internal/service/user_service.go
- scripts/check-env.sh
章节来源
- pkg/config/config.go
- pkg/config/manager.go
- pkg/auth/jwt.go
- pkg/auth/manager.go
- internal/handler/auth_handler.go
- internal/service/user_service.go
- scripts/check-env.sh
核心组件
- 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
- pkg/config/config.go
- pkg/config/config.go
- pkg/auth/jwt.go
- pkg/auth/manager.go
- internal/service/user_service.go
- scripts/check-env.sh
架构总览
下图展示JWT配置从环境变量到服务使用的端到端流程。
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
- pkg/config/manager.go
- pkg/auth/manager.go
- pkg/auth/jwt.go
- internal/handler/auth_handler.go
- internal/service/user_service.go
详细组件分析
JWTConfig与默认值
- 结构体定义
- Secret:字符串,用于签名与验证JWT
- ExpireHours:整数,令牌有效期(小时),默认168(7天)
- 默认值来源
- 通过Viper设置默认值,确保未提供环境变量时仍能运行
- 环境变量映射
- JWT_SECRET → jwt.secret
- JWT_EXPIRE_HOURS → jwt.expire_hours
章节来源
JWTService与Claims
- JWTService
- 字段:secretKey、expireHours
- 方法:GenerateToken、ValidateToken
- Claims
- 包含用户ID、用户名、角色以及标准声明(签发时间、过期时间、生效时间、发行者等)
- 令牌生成
- 使用HS256算法签名,过期时间基于expireHours计算
- 令牌验证
- 使用同一secretKey进行验证,若签名不符或过期则报错
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 : "生成/验证"
图表来源
章节来源
JWT服务管理器
- Init(cfg)
- 仅初始化一次,使用sync.Once保证幂等
- 将cfg中的Secret与ExpireHours注入JWTService
- GetJWTService/MustGetJWTService
- 提供全局唯一实例访问;未初始化时报错或panic
flowchart TD
Start(["调用 auth.Init(cfg)"]) --> Once{"是否已初始化?"}
Once --> |否| Create["创建JWTService实例<br/>注入Secret/ExpireHours"]
Once --> |是| Skip["跳过初始化"]
Create --> Done(["完成"])
Skip --> Done
图表来源
章节来源
认证服务与JWT集成
- 登录/注册成功后,业务层调用JWTService生成令牌
- 处理器层接收令牌并返回给客户端
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"
图表来源
章节来源
环境变量覆盖与安全检查
- 环境变量映射
- JWT_SECRET → jwt.secret
- JWT_EXPIRE_HOURS → jwt.expire_hours
- 默认值
- ExpireHours默认168(7天)
- 安全检查
- 脚本会检查JWT_SECRET长度是否小于32字符,并提示使用默认密钥的风险
章节来源
依赖关系分析
- 配置层
- config.Load负责从.env与环境变量加载配置,设置默认值并映射JWT相关键
- config.Init提供全局配置单例
- 认证层
- auth.Init接收JWTConfig,创建JWTService实例
- auth.GetJWTService/MustGetJWTService提供全局访问
- 业务层
- handler.Login/Register通过MustGetJWTService获取JWTService
- service.LoginUser/RegisterUser调用JWTService生成令牌
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
- pkg/config/manager.go
- pkg/auth/manager.go
- internal/handler/auth_handler.go
- internal/service/user_service.go
章节来源
- pkg/config/config.go
- pkg/config/manager.go
- pkg/auth/manager.go
- internal/handler/auth_handler.go
- internal/service/user_service.go
性能考量
- 令牌生成与验证均为内存操作,开销极低
- 过期时间越长,客户端缓存令牌的时间越久,减少鉴权次数;但会增加泄露风险
- 建议在移动端或易泄露设备上缩短expire_hours,在可信环境适当延长
故障排查指南
- JWT服务未初始化
- 现象:调用GetJWTService/MustGetJWTService时报错或panic
- 排查:确认已在应用启动阶段调用auth.Init(cfg)
- 令牌无效
- 现象:ValidateToken返回错误
- 排查:确认使用相同的JWT_SECRET;检查网络传输是否篡改;核对过期时间
- 环境变量未生效
- 现象:JWT_EXPIRE_HOURS未按预期
- 排查:确认环境变量名正确且已导出;检查.env文件路径与加载顺序
章节来源
结论
- jwt.secret用于签名与验证JWT,必须保密且足够随机
- expire_hours控制令牌有效期,默认168小时(7天),可通过JWT_EXPIRE_HOURS覆盖
- 通过JWT_SECRET与JWT_EXPIRE_HOURS实现安全可控的令牌策略
- 建议在生产环境使用长随机密钥,并根据业务场景调整有效期
附录
安全最佳实践
- 密钥生成建议
- 使用足够长度的随机字符串作为JWT_SECRET(建议≥32字符)
- 避免使用默认密钥或弱口令
- 有效期设置策略
- 移动端/公共设备:较短有效期(如24-72小时)
- 可信服务间:可适当延长(如7天)
- 环境变量管理
- 在部署时通过环境变量覆盖,避免硬编码
- 使用脚本检查密钥长度与默认值风险
章节来源