# 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)