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:
310
.qoder/repowiki/zh/content/认证与授权/JWT认证.md
Normal file
310
.qoder/repowiki/zh/content/认证与授权/JWT认证.md
Normal file
@@ -0,0 +1,310 @@
|
||||
# JWT认证
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [manager.go](file://pkg/auth/manager.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [config.go](file://pkg/config/config.go)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [JWT服务结构设计](#jwt服务结构设计)
|
||||
3. [令牌生成与验证机制](#令牌生成与验证机制)
|
||||
4. [认证中间件实现](#认证中间件实现)
|
||||
5. [JWT工作流程](#jwt工作流程)
|
||||
6. [密钥管理与安全策略](#密钥管理与安全策略)
|
||||
7. [单例模式应用](#单例模式应用)
|
||||
8. [最佳实践](#最佳实践)
|
||||
|
||||
## 简介
|
||||
CarrotSkin项目采用基于JWT(JSON Web Token)的用户认证机制,为系统提供安全、无状态的用户身份验证。该机制通过在客户端和服务器之间传递加密的令牌来验证用户身份,避免了传统会话存储的服务器状态管理开销。本文档详细阐述了JWT服务的实现原理、核心组件设计以及在Gin框架中的集成方式,为开发者提供全面的技术参考。
|
||||
|
||||
## JWT服务结构设计
|
||||
|
||||
JWT服务的核心是`JWTService`结构体,它封装了令牌生成和验证所需的所有配置和方法。该服务通过`Claims`结构体定义了令牌中包含的用户声明信息。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class JWTService {
|
||||
-secretKey string
|
||||
-expireHours int
|
||||
+GenerateToken(userID int64, username string, role string) (string, error)
|
||||
+ValidateToken(tokenString string) (*Claims, error)
|
||||
}
|
||||
class Claims {
|
||||
+UserID int64
|
||||
+Username string
|
||||
+Role string
|
||||
+RegisteredClaims jwt.RegisteredClaims
|
||||
}
|
||||
JWTService --> Claims : "包含"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L11-L14)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L25-L30)
|
||||
|
||||
**Section sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L11-L71)
|
||||
|
||||
## 令牌生成与验证机制
|
||||
|
||||
### 令牌生成(GenerateToken)
|
||||
`GenerateToken`方法负责创建JWT令牌,它接收用户ID、用户名和角色作为参数,构建包含这些信息的声明(Claims),并使用预设的密钥进行签名。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始生成令牌]) --> CreateClaims["创建声明对象<br/>包含user_id、username、role"]
|
||||
CreateClaims --> SetExpiry["设置过期时间<br/>(当前时间 + expireHours)"]
|
||||
SetExpiry --> SetIssued["设置签发时间<br/>(当前时间)"]
|
||||
SetIssued --> SetNotBefore["设置生效时间<br/>(当前时间)"]
|
||||
SetNotBefore --> SetIssuer["设置发行者<br/>(carrotskin)"]
|
||||
SetIssuer --> CreateToken["创建JWT令牌<br/>使用HS256算法"]
|
||||
CreateToken --> SignToken["使用secretKey签名"]
|
||||
SignToken --> ReturnToken["返回签名后的令牌字符串"]
|
||||
ReturnToken --> End([结束])
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L33-L53)
|
||||
|
||||
### 令牌验证(ValidateToken)
|
||||
`ValidateToken`方法负责验证接收到的JWT令牌的有效性,包括签名验证、过期检查和声明解析。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始验证令牌]) --> ParseToken["解析令牌字符串"]
|
||||
ParseToken --> CheckSignature["验证签名<br/>使用secretKey"]
|
||||
CheckSignature --> IsValid{"签名有效?"}
|
||||
IsValid --> |否| ReturnError["返回错误<br/>无效的token"]
|
||||
IsValid --> |是| CheckClaims["检查声明对象"]
|
||||
CheckClaims --> IsClaimsValid{"声明类型正确<br/>且令牌有效?"}
|
||||
IsClaimsValid --> |否| ReturnError
|
||||
IsClaimsValid --> |是| ReturnClaims["返回解析出的Claims对象"]
|
||||
ReturnClaims --> End([结束])
|
||||
ReturnError --> End
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L56-L70)
|
||||
|
||||
**Section sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L32-L70)
|
||||
|
||||
## 认证中间件实现
|
||||
|
||||
CarrotSkin项目提供了两种认证中间件:强制认证中间件(AuthMiddleware)和可选认证中间件(OptionalAuthMiddleware),它们在Gin框架中拦截HTTP请求并处理Authorization头。
|
||||
|
||||
### 强制认证中间件(AuthMiddleware)
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Middleware as "AuthMiddleware"
|
||||
participant JWTService as "JWTService"
|
||||
Client->>Middleware : 发送请求<br/>Authorization : Bearer token
|
||||
Middleware->>Middleware : 获取Authorization头
|
||||
alt 头部为空
|
||||
Middleware-->>Client : 返回401<br/>缺少Authorization头
|
||||
return
|
||||
end
|
||||
Middleware->>Middleware : 解析Bearer格式
|
||||
alt 格式无效
|
||||
Middleware-->>Client : 返回401<br/>无效的Authorization头格式
|
||||
return
|
||||
end
|
||||
Middleware->>JWTService : 调用ValidateToken(token)
|
||||
alt 验证失败
|
||||
JWTService-->>Middleware : 返回错误
|
||||
Middleware-->>Client : 返回401<br/>无效的token
|
||||
return
|
||||
end
|
||||
JWTService-->>Middleware : 返回Claims对象
|
||||
Middleware->>Middleware : 将用户信息存入上下文<br/>(user_id, username, role)
|
||||
Middleware->>Client : 继续处理请求
|
||||
```
|
||||
|
||||
### 可选认证中间件(OptionalAuthMiddleware)
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Middleware as "OptionalAuthMiddleware"
|
||||
participant JWTService as "JWTService"
|
||||
Client->>Middleware : 发送请求<br/>Authorization : Bearer token
|
||||
Middleware->>Middleware : 获取Authorization头
|
||||
alt 头部存在
|
||||
Middleware->>Middleware : 解析Bearer格式
|
||||
alt 格式正确
|
||||
Middleware->>JWTService : 调用ValidateToken(token)
|
||||
alt 验证成功
|
||||
JWTService-->>Middleware : 返回Claims对象
|
||||
Middleware->>Middleware : 将用户信息存入上下文
|
||||
end
|
||||
end
|
||||
end
|
||||
Middleware->>Client : 继续处理请求<br/>(无论认证成功与否)
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [auth.go](file://internal/middleware/auth.go#L13-L55)
|
||||
- [auth.go](file://internal/middleware/auth.go#L58-L78)
|
||||
|
||||
**Section sources**
|
||||
- [auth.go](file://internal/middleware/auth.go#L1-L79)
|
||||
|
||||
## JWT工作流程
|
||||
|
||||
以下是用户从登录到访问受保护资源的完整JWT工作流程:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as "用户"
|
||||
participant Frontend as "前端"
|
||||
participant Backend as "后端"
|
||||
User->>Frontend : 输入用户名/邮箱和密码
|
||||
Frontend->>Backend : POST /api/v1/auth/login
|
||||
Backend->>Backend : 调用LoginUser服务
|
||||
Backend->>Backend : 验证用户凭证
|
||||
alt 验证成功
|
||||
Backend->>Backend : 调用JWTService.GenerateToken
|
||||
Backend->>Backend : 生成JWT令牌
|
||||
Backend-->>Frontend : 返回200<br/>{token, userInfo}
|
||||
Frontend->>Frontend : 存储令牌
|
||||
User->>Frontend : 访问受保护页面
|
||||
Frontend->>Backend : GET /api/v1/protected<br/>Authorization : Bearer token
|
||||
Backend->>Backend : AuthMiddleware拦截请求
|
||||
Backend->>Backend : 解析Authorization头
|
||||
Backend->>Backend : 调用JWTService.ValidateToken
|
||||
Backend->>Backend : 验证令牌有效性
|
||||
Backend->>Backend : 提取用户信息存入上下文
|
||||
Backend->>Backend : 继续处理业务逻辑
|
||||
Backend-->>Frontend : 返回请求数据
|
||||
else 验证失败
|
||||
Backend-->>Frontend : 返回401<br/>登录失败
|
||||
end
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L71-L122)
|
||||
- [auth.go](file://internal/middleware/auth.go#L13-L55)
|
||||
|
||||
**Section sources**
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go#L97-L147)
|
||||
- [user_service.go](file://internal/service/user_service.go#L71-L122)
|
||||
|
||||
## 密钥管理与安全策略
|
||||
|
||||
### 配置管理
|
||||
JWT服务的配置通过`config.go`文件中的`JWTConfig`结构体进行管理,支持环境变量注入,确保密钥的安全性。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class JWTConfig {
|
||||
+Secret string
|
||||
+ExpireHours int
|
||||
}
|
||||
class Config {
|
||||
+Server ServerConfig
|
||||
+Database DatabaseConfig
|
||||
+Redis RedisConfig
|
||||
+JWT JWTConfig
|
||||
+Casbin CasbinConfig
|
||||
+Log LogConfig
|
||||
+Upload UploadConfig
|
||||
+Email EmailConfig
|
||||
}
|
||||
Config --> JWTConfig : "包含"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [config.go](file://pkg/config/config.go#L68-L71)
|
||||
- [config.go](file://pkg/config/config.go#L14-L24)
|
||||
|
||||
### 安全声明
|
||||
JWT令牌中包含的声明(Claims)具有重要的安全意义:
|
||||
|
||||
- **user_id**: 用户唯一标识,用于在系统中识别用户身份
|
||||
- **username**: 用户名,用于显示和审计
|
||||
- **role**: 用户角色,用于基于角色的访问控制(RBAC)
|
||||
- **ExpiresAt**: 过期时间,防止令牌长期有效
|
||||
- **IssuedAt**: 签发时间,用于审计和令牌生命周期管理
|
||||
- **NotBefore**: 生效时间,可用于延迟生效的令牌
|
||||
- **Issuer**: 发行者,确保令牌来自可信源
|
||||
|
||||
**Section sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L25-L30)
|
||||
- [config.go](file://pkg/config/config.go#L68-L71)
|
||||
|
||||
## 单例模式应用
|
||||
|
||||
`MustGetJWTService`函数实现了线程安全的单例模式,确保在整个应用程序生命周期中只存在一个JWT服务实例。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Init as "初始化"
|
||||
participant Get as "GetJWTService"
|
||||
participant MustGet as "MustGetJWTService"
|
||||
participant Once as "sync.Once"
|
||||
Init->>Once : 调用Init(cfg)
|
||||
Once->>Once : 检查是否已执行
|
||||
alt 首次调用
|
||||
Once->>Init : 执行初始化
|
||||
Init->>jwtServiceInstance : 创建JWTService实例
|
||||
Init-->>Once : 标记已执行
|
||||
else 非首次调用
|
||||
Once-->>Init : 跳过执行
|
||||
end
|
||||
Get->>Get : 检查jwtServiceInstance
|
||||
alt 实例存在
|
||||
Get-->>Get : 返回实例
|
||||
else 实例不存在
|
||||
Get-->>Get : 返回错误
|
||||
end
|
||||
MustGet->>Get : 调用GetJWTService
|
||||
alt 获取成功
|
||||
Get-->>MustGet : 返回实例
|
||||
MustGet-->>MustGet : 返回实例
|
||||
else 获取失败
|
||||
Get-->>MustGet : 返回错误
|
||||
MustGet->>MustGet : panic(错误)
|
||||
end
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [manager.go](file://pkg/auth/manager.go#L9-L45)
|
||||
|
||||
**Section sources**
|
||||
- [manager.go](file://pkg/auth/manager.go#L9-L45)
|
||||
|
||||
## 最佳实践
|
||||
|
||||
### 密钥管理
|
||||
- JWT密钥(`secretKey`)应通过环境变量配置,避免硬编码在代码中
|
||||
- 使用足够长度的随机字符串作为密钥,提高安全性
|
||||
- 定期轮换密钥(虽然当前实现不支持,但架构上可以扩展)
|
||||
|
||||
### 过期策略
|
||||
- 当前默认过期时间为168小时(7天),可通过`JWT_EXPIRE_HOURS`环境变量调整
|
||||
- 对于敏感操作,建议使用短期令牌或结合刷新令牌机制
|
||||
- 过期时间不宜过长,以降低令牌泄露后的风险
|
||||
|
||||
### 防止重放攻击
|
||||
- 虽然JWT本身是无状态的,但可以通过以下方式增强安全性:
|
||||
- 使用短期令牌
|
||||
- 在Redis中维护已注销令牌的黑名单
|
||||
- 结合客户端指纹(如IP地址、User-Agent)进行额外验证
|
||||
- 当前实现中,`OptionalAuthMiddleware`提供了基础的灵活性,允许部分接口在认证失败时仍能访问
|
||||
|
||||
### 性能考虑
|
||||
- JWT验证是计算密集型操作,但在现代硬件上性能良好
|
||||
- 使用HS256算法在安全性和性能之间取得了良好平衡
|
||||
- 避免在令牌中存储过多信息,以减小令牌大小和传输开销
|
||||
|
||||
**Section sources**
|
||||
- [config.go](file://pkg/config/config.go#L164)
|
||||
- [manager.go](file://pkg/auth/manager.go#L18-L23)
|
||||
- [jwt.go](file://pkg/auth/jwt.go#L39-L43)
|
||||
211
.qoder/repowiki/zh/content/认证与授权/RBAC权限控制.md
Normal file
211
.qoder/repowiki/zh/content/认证与授权/RBAC权限控制.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# RBAC权限控制
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [user_repository.go](file://internal/repository/user_repository.go)
|
||||
- [audit_log.go](file://internal/model/audit_log.go)
|
||||
- [config.go](file://pkg/config/config.go)
|
||||
- [carrotskin_postgres.sql](file://scripts/carrotskin_postgres.sql)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [项目结构](#项目结构)
|
||||
2. [核心组件](#核心组件)
|
||||
3. [架构概述](#架构概述)
|
||||
4. [详细组件分析](#详细组件分析)
|
||||
5. [依赖分析](#依赖分析)
|
||||
6. [性能考虑](#性能考虑)
|
||||
7. [故障排除指南](#故障排除指南)
|
||||
8. [结论](#结论)
|
||||
|
||||
## 项目结构
|
||||
|
||||
项目采用分层架构设计,权限控制相关文件主要分布在`configs/casbin/`和`internal/middleware/`目录下。`rbac_model.conf`文件定义了基于Casbin的RBAC权限模型,而`auth.go`文件实现了JWT认证中间件,为权限系统提供用户身份验证。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "配置"
|
||||
rbac_model_conf[rbac_model.conf]
|
||||
end
|
||||
subgraph "中间件"
|
||||
auth_go[auth.go]
|
||||
end
|
||||
subgraph "服务层"
|
||||
user_service_go[user_service.go]
|
||||
end
|
||||
subgraph "数据模型"
|
||||
audit_log_go[audit_log.go]
|
||||
end
|
||||
rbac_model_conf --> auth_go
|
||||
auth_go --> user_service_go
|
||||
user_service_go --> audit_log_go
|
||||
```
|
||||
|
||||
**图示来源**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [audit_log.go](file://internal/model/audit_log.go)
|
||||
|
||||
**本节来源**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
|
||||
## 核心组件
|
||||
|
||||
系统的核心权限控制组件包括Casbin权限模型配置、JWT认证中间件和用户服务。`rbac_model.conf`文件定义了请求定义、策略定义、角色定义、匹配器和策略效果等关键部分。`auth.go`文件中的`AuthMiddleware`函数实现了JWT认证逻辑,确保只有经过身份验证的用户才能访问受保护的资源。`user_service.go`文件中的用户服务函数处理用户注册、登录等操作,并在注册时为新用户分配默认角色。
|
||||
|
||||
**本节来源**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
|
||||
## 架构概述
|
||||
|
||||
系统采用基于Casbin的RBAC(基于角色的访问控制)权限模型。该模型通过`rbac_model.conf`文件定义,包含请求定义、策略定义、角色定义、匹配器和策略效果五个部分。JWT认证中间件负责用户身份验证,将用户信息存储在请求上下文中。用户服务处理用户相关的业务逻辑,并在注册时为用户分配角色。权限检查在中间件或服务层进行,通过将用户角色(role)与访问资源(obj)和操作(act)进行匹配来决定是否允许访问。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[客户端] --> B[JWT认证中间件]
|
||||
B --> C{身份验证}
|
||||
C --> |成功| D[权限检查]
|
||||
C --> |失败| E[返回401]
|
||||
D --> F{权限允许?}
|
||||
F --> |是| G[执行操作]
|
||||
F --> |否| H[返回403]
|
||||
G --> I[返回结果]
|
||||
```
|
||||
|
||||
**图示来源**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### RBAC模型配置分析
|
||||
|
||||
`rbac_model.conf`文件定义了系统的权限模型。请求定义`r = sub, obj, act`表示权限检查请求包含主体(用户或角色)、对象(资源)和动作(操作)三个部分。策略定义`p = sub, obj, act`定义了权限策略的结构。角色定义`g = _, _`用于建立角色继承关系。匹配器`m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`是权限检查的核心逻辑,它首先通过`g(r.sub, p.sub)`检查请求主体是否具有策略主体的角色,然后检查请求的对象和动作是否与策略匹配。策略效果`e = some(where (p.eft == allow))`表示只要存在一条允许的策略,就允许访问。
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class RBACModel {
|
||||
+request_definition : r = sub, obj, act
|
||||
+policy_definition : p = sub, obj, act
|
||||
+role_definition : g = _, _
|
||||
+matchers : m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
|
||||
+policy_effect : e = some(where (p.eft == allow))
|
||||
}
|
||||
```
|
||||
|
||||
**图示来源**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
|
||||
**本节来源**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
|
||||
### JWT认证中间件分析
|
||||
|
||||
`auth.go`文件中的`AuthMiddleware`函数实现了JWT认证中间件。该中间件从请求头中提取JWT令牌,验证其有效性,并将用户信息存储在请求上下文中。`OptionalAuthMiddleware`函数提供了可选的JWT认证,允许未认证用户访问某些资源。这两个中间件为系统的权限控制提供了基础的身份验证功能。
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 客户端
|
||||
participant Middleware as 认证中间件
|
||||
participant JWTService as JWT服务
|
||||
Client->>Middleware : 发送请求(Authorization头)
|
||||
Middleware->>Middleware : 检查Authorization头
|
||||
alt 头部不存在
|
||||
Middleware-->>Client : 返回401(缺少Authorization头)
|
||||
else 有效格式
|
||||
Middleware->>JWTService : 验证令牌
|
||||
alt 令牌有效
|
||||
JWTService-->>Middleware : 返回用户声明
|
||||
Middleware->>Middleware : 将用户信息存入上下文
|
||||
Middleware->>Client : 继续处理请求
|
||||
else 令牌无效
|
||||
Middleware-->>Client : 返回401(无效的token)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
**图示来源**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
|
||||
**本节来源**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
|
||||
### 用户服务分析
|
||||
|
||||
`user_service.go`文件中的`RegisterUser`函数处理用户注册逻辑。在创建用户时,该函数将用户的`Role`字段设置为"user",为新用户分配默认角色。`LoginUser`函数处理用户登录,验证用户名/邮箱和密码的正确性,并在成功登录后生成JWT令牌。这些服务函数与权限系统紧密集成,确保用户在注册和登录时正确地获得和验证其角色。
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([注册用户]) --> CheckUsername["检查用户名是否已存在"]
|
||||
CheckUsername --> UsernameExists{"用户名已存在?"}
|
||||
UsernameExists --> |是| ReturnError1["返回错误: 用户名已存在"]
|
||||
UsernameExists --> |否| CheckEmail["检查邮箱是否已存在"]
|
||||
CheckEmail --> EmailExists{"邮箱已存在?"}
|
||||
EmailExists --> |是| ReturnError2["返回错误: 邮箱已被注册"]
|
||||
EmailExists --> |否| HashPassword["加密密码"]
|
||||
HashPassword --> CreateAvatar["确定头像URL"]
|
||||
CreateAvatar --> CreateUser["创建用户(角色=user)"]
|
||||
CreateUser --> GenerateToken["生成JWT Token"]
|
||||
GenerateToken --> ReturnSuccess["返回用户信息和Token"]
|
||||
ReturnError1 --> End([结束])
|
||||
ReturnError2 --> End
|
||||
ReturnSuccess --> End
|
||||
```
|
||||
|
||||
**图示来源**
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
|
||||
**本节来源**
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
|
||||
## 依赖分析
|
||||
|
||||
系统各组件之间存在明确的依赖关系。`auth.go`依赖于`pkg/auth/jwt.go`提供的JWT服务进行令牌验证。`user_service.go`依赖于`repository/user_repository.go`进行数据库操作,并依赖于`pkg/auth/password.go`进行密码加密。`rbac_model.conf`被Casbin引擎读取,用于定义权限模型。这些依赖关系确保了系统的模块化和可维护性。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[auth.go] --> B[jwt.go]
|
||||
C[user_service.go] --> D[user_repository.go]
|
||||
C --> E[password.go]
|
||||
F[rbac_model.conf] --> G[Casbin引擎]
|
||||
```
|
||||
|
||||
**图示来源**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [user_repository.go](file://internal/repository/user_repository.go)
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
|
||||
**本节来源**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [user_repository.go](file://internal/repository/user_repository.go)
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
|
||||
## 性能考虑
|
||||
|
||||
系统的权限控制设计考虑了性能因素。JWT令牌在客户端存储,减少了服务器的认证开销。Casbin的权限检查算法经过优化,能够快速匹配权限策略。数据库查询使用了适当的索引,如`casbin_rule`表上的`ptype`、`v0`、`v1`索引,提高了权限检查的效率。对于高并发场景,可以考虑将权限策略缓存到Redis中,进一步提高性能。
|
||||
|
||||
## 故障排除指南
|
||||
|
||||
当遇到权限相关问题时,可以按照以下步骤进行排查:
|
||||
1. 检查JWT令牌是否正确生成和传递。
|
||||
2. 验证`rbac_model.conf`文件的语法是否正确。
|
||||
3. 检查数据库中的`casbin_rule`表是否包含正确的权限策略。
|
||||
4. 确认用户的角色是否正确分配。
|
||||
5. 查看系统日志,寻找权限拒绝的记录。
|
||||
|
||||
**本节来源**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [audit_log.go](file://internal/model/audit_log.go)
|
||||
|
||||
## 结论
|
||||
|
||||
本系统采用基于Casbin的RBAC权限模型,通过`rbac_model.conf`文件定义权限策略,使用JWT认证中间件进行身份验证。该设计提供了灵活、可扩展的权限控制机制,能够满足不同场景下的权限管理需求。通过合理配置权限策略,可以实现细粒度的访问控制,确保系统的安全性。
|
||||
326
.qoder/repowiki/zh/content/认证与授权/认证与授权.md
Normal file
326
.qoder/repowiki/zh/content/认证与授权/认证与授权.md
Normal file
@@ -0,0 +1,326 @@
|
||||
# 认证与授权
|
||||
|
||||
<cite>
|
||||
**本文档引用的文件**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [manager.go](file://pkg/auth/manager.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [token.go](file://internal/model/token.go)
|
||||
- [token_service.go](file://internal/service/token_service.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [user.go](file://internal/model/user.go)
|
||||
- [config.go](file://pkg/config/config.go)
|
||||
- [routes.go](file://internal/handler/routes.go)
|
||||
- [audit_log.go](file://internal/model/audit_log.go)
|
||||
</cite>
|
||||
|
||||
## 目录
|
||||
1. [简介](#简介)
|
||||
2. [项目结构](#项目结构)
|
||||
3. [核心组件](#核心组件)
|
||||
4. [架构概述](#架构概述)
|
||||
5. [详细组件分析](#详细组件分析)
|
||||
6. [依赖分析](#依赖分析)
|
||||
7. [性能考虑](#性能考虑)
|
||||
8. [故障排除指南](#故障排除指南)
|
||||
9. [结论](#结论)
|
||||
|
||||
## 简介
|
||||
CarrotSkin项目实现了一套完整的认证与授权安全机制,采用JWT(JSON Web Token)进行用户认证,并结合Casbin实现基于角色的访问控制(RBAC)。该系统为用户提供安全的注册、登录、密码重置功能,同时通过中间件对API请求进行权限验证。本文档详细说明了系统的安全架构、JWT认证流程、Casbin权限模型配置以及认证中间件的实现细节。
|
||||
|
||||
## 项目结构
|
||||
CarrotSkin项目的认证与授权相关代码分布在多个目录中,形成了清晰的分层架构。核心安全功能主要集中在`pkg/auth`包中,而具体的业务逻辑则分布在`internal`目录下的各个模块。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "配置"
|
||||
config[configs/casbin/rbac_model.conf]
|
||||
end
|
||||
subgraph "内部处理"
|
||||
handler[internal/handler]
|
||||
middleware[internal/middleware]
|
||||
model[internal/model]
|
||||
service[internal/service]
|
||||
repository[internal/repository]
|
||||
end
|
||||
subgraph "公共包"
|
||||
auth[pkg/auth]
|
||||
config_pkg[pkg/config]
|
||||
database[pkg/database]
|
||||
redis[pkg/redis]
|
||||
end
|
||||
config --> auth
|
||||
auth --> middleware
|
||||
middleware --> handler
|
||||
handler --> service
|
||||
service --> repository
|
||||
repository --> database
|
||||
service --> redis
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
|
||||
**Section sources**
|
||||
- [project_structure](file://project_structure)
|
||||
|
||||
## 核心组件
|
||||
CarrotSkin项目的认证与授权系统由多个核心组件构成,包括JWT服务、认证中间件、Casbin权限管理器、用户服务和令牌服务。这些组件协同工作,确保系统的安全性。
|
||||
|
||||
**Section sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [token_service.go](file://internal/service/token_service.go)
|
||||
|
||||
## 架构概述
|
||||
CarrotSkin的认证与授权架构采用分层设计,从下到上的层次包括:配置层、认证服务层、中间件层、处理器层和路由层。这种设计实现了关注点分离,提高了代码的可维护性和可测试性。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[客户端] --> B[HTTP请求]
|
||||
B --> C{路由}
|
||||
C --> D[/认证路由\n无需JWT/]
|
||||
C --> E[/受保护路由\n需要JWT/]
|
||||
D --> F[auth_handler]
|
||||
E --> G[AuthMiddleware]
|
||||
G --> H{验证JWT}
|
||||
H --> |有效| I[业务处理器]
|
||||
H --> |无效| J[返回401]
|
||||
I --> K[service]
|
||||
K --> L[repository]
|
||||
L --> M[(数据库)]
|
||||
G --> N[Casbin权限检查]
|
||||
N --> |允许| I
|
||||
N --> |拒绝| O[返回403]
|
||||
P[JWT配置] --> Q[jwt.go]
|
||||
Q --> R[AuthMiddleware]
|
||||
S[Casbin配置] --> T[CasbinRule]
|
||||
T --> N
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [routes.go](file://internal/handler/routes.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [config.go](file://pkg/config/config.go)
|
||||
- [audit_log.go](file://internal/model/audit_log.go)
|
||||
|
||||
## 详细组件分析
|
||||
|
||||
### JWT认证服务分析
|
||||
JWT认证服务是CarrotSkin安全机制的核心,负责生成和验证JWT令牌。该服务实现了标准的JWT功能,包括令牌的签发、验证和声明管理。
|
||||
|
||||
#### JWT服务类图
|
||||
```mermaid
|
||||
classDiagram
|
||||
class JWTService {
|
||||
+string secretKey
|
||||
+int expireHours
|
||||
+GenerateToken(userID int64, username string, role string) (string, error)
|
||||
+ValidateToken(tokenString string) (*Claims, error)
|
||||
}
|
||||
class Claims {
|
||||
+int64 UserID
|
||||
+string Username
|
||||
+string Role
|
||||
+jwt.RegisteredClaims
|
||||
}
|
||||
class JWTManager {
|
||||
-static *JWTService jwtServiceInstance
|
||||
-static sync.Once once
|
||||
+Init(cfg JWTConfig) error
|
||||
+GetJWTService() (*JWTService, error)
|
||||
+MustGetJWTService() *JWTService
|
||||
}
|
||||
JWTManager --> JWTService : "创建"
|
||||
JWTService --> Claims : "包含"
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [manager.go](file://pkg/auth/manager.go)
|
||||
|
||||
**Section sources**
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [manager.go](file://pkg/auth/manager.go)
|
||||
|
||||
### 认证中间件分析
|
||||
认证中间件负责在请求处理流程中验证JWT令牌的有效性。它拦截所有受保护的API请求,确保只有携带有效令牌的请求才能访问受保护的资源。
|
||||
|
||||
#### 认证中间件流程图
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> GetHeader["获取Authorization头"]
|
||||
GetHeader --> HeaderEmpty{"头为空?"}
|
||||
HeaderEmpty --> |是| Return401Unauthorized["返回401未授权"]
|
||||
HeaderEmpty --> |否| ParseHeader["解析Bearer格式"]
|
||||
ParseHeader --> FormatValid{"格式有效?"}
|
||||
FormatValid --> |否| Return401InvalidFormat["返回401无效格式"]
|
||||
FormatValid --> |是| ExtractToken["提取Token"]
|
||||
ExtractToken --> ValidateToken["验证Token"]
|
||||
ValidateToken --> TokenValid{"Token有效?"}
|
||||
TokenValid --> |否| Return401InvalidToken["返回401无效Token"]
|
||||
TokenValid --> |是| StoreUserInfo["将用户信息存入上下文"]
|
||||
StoreUserInfo --> Next["调用下一个处理器"]
|
||||
Next --> End([结束])
|
||||
Return401Unauthorized --> End
|
||||
Return401InvalidFormat --> End
|
||||
Return401InvalidToken --> End
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
|
||||
**Section sources**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
|
||||
### Casbin RBAC权限模型分析
|
||||
CarrotSkin使用Casbin实现基于角色的访问控制(RBAC)模型,通过配置文件定义权限策略,实现灵活的权限管理。
|
||||
|
||||
#### Casbin RBAC模型配置
|
||||
```conf
|
||||
[request_definition]
|
||||
r = sub, obj, act
|
||||
|
||||
[policy_definition]
|
||||
p = sub, obj, act
|
||||
|
||||
[role_definition]
|
||||
g = _, _
|
||||
|
||||
[policy_effect]
|
||||
e = some(where (p.eft == allow))
|
||||
|
||||
[matchers]
|
||||
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
|
||||
**Section sources**
|
||||
- [rbac_model.conf](file://configs/casbin/rbac_model.conf)
|
||||
|
||||
### 用户认证流程分析
|
||||
用户认证流程涵盖了从注册、登录到密码重置的完整生命周期,确保用户身份的安全管理。
|
||||
|
||||
#### 用户认证流程序列图
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as "客户端"
|
||||
participant Handler as "AuthHandler"
|
||||
participant Service as "UserService"
|
||||
participant JWT as "JWTService"
|
||||
participant DB as "数据库"
|
||||
Client->>Handler : POST /api/v1/auth/register
|
||||
Handler->>Service : RegisterUser()
|
||||
Service->>DB : 检查用户名/邮箱是否存在
|
||||
DB-->>Service : 返回检查结果
|
||||
Service->>JWT : HashPassword()
|
||||
Service->>DB : 创建用户记录
|
||||
DB-->>Service : 用户对象
|
||||
Service->>JWT : GenerateToken()
|
||||
JWT-->>Service : JWT Token
|
||||
Service-->>Handler : 用户和Token
|
||||
Handler-->>Client : 200 OK {token, userInfo}
|
||||
Client->>Handler : POST /api/v1/auth/login
|
||||
Handler->>Service : LoginUser()
|
||||
Service->>DB : 查找用户(用户名/邮箱)
|
||||
DB-->>Service : 用户对象
|
||||
Service->>JWT : CheckPassword()
|
||||
Service->>JWT : GenerateToken()
|
||||
JWT-->>Service : JWT Token
|
||||
Service-->>Handler : 用户和Token
|
||||
Handler-->>Client : 200 OK {token, userInfo}
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
|
||||
**Section sources**
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [user_service.go](file://internal/service/user_service.go)
|
||||
|
||||
## 依赖分析
|
||||
CarrotSkin的认证与授权系统依赖于多个外部包和内部组件,形成了复杂的依赖关系网络。
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[pkg/auth] --> B[github.com/golang-jwt/jwt/v5]
|
||||
A --> C[pkg/config]
|
||||
D[internal/middleware] --> A
|
||||
D --> E[github.com/gin-gonic/gin]
|
||||
F[internal/handler] --> D
|
||||
F --> G[internal/service]
|
||||
G --> A
|
||||
G --> H[pkg/database]
|
||||
G --> I[pkg/redis]
|
||||
J[pkg/config] --> K[github.com/spf13/viper]
|
||||
J --> L[github.com/joho/godotenv]
|
||||
H --> M[gorm.io/gorm]
|
||||
I --> N[github.com/redis/go-redis]
|
||||
```
|
||||
|
||||
**Diagram sources**
|
||||
- [go.mod](file://go.mod)
|
||||
- [jwt.go](file://pkg/auth/jwt.go)
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
|
||||
**Section sources**
|
||||
- [go.mod](file://go.mod)
|
||||
- [go.sum](file://go.sum)
|
||||
|
||||
## 性能考虑
|
||||
CarrotSkin的认证与授权系统在设计时考虑了性能因素,通过多种机制确保系统的高效运行。
|
||||
|
||||
1. **JWT令牌验证**:JWT令牌的验证是无状态的,不需要查询数据库,大大提高了验证速度。
|
||||
2. **Redis缓存**:系统使用Redis存储验证码等临时数据,减少了数据库的压力。
|
||||
3. **连接池**:数据库和Redis都使用了连接池,避免了频繁创建和销毁连接的开销。
|
||||
4. **异步操作**:某些非关键操作(如清理多余令牌)使用goroutine异步执行,不影响主流程性能。
|
||||
5. **批量操作**:在清理多余令牌时,使用批量删除操作,减少了数据库交互次数。
|
||||
|
||||
**Section sources**
|
||||
- [token_service.go](file://internal/service/token_service.go)
|
||||
- [repository/token_repository.go](file://internal/repository/token_repository.go)
|
||||
- [config.go](file://pkg/config/config.go)
|
||||
|
||||
## 故障排除指南
|
||||
当遇到认证与授权相关的问题时,可以参考以下常见问题的解决方案:
|
||||
|
||||
1. **401 Unauthorized错误**:
|
||||
- 检查请求头中是否包含`Authorization`头
|
||||
- 确认`Authorization`头的格式是否为`Bearer <token>`
|
||||
- 验证JWT令牌是否已过期
|
||||
- 检查JWT密钥配置是否正确
|
||||
|
||||
2. **403 Forbidden错误**:
|
||||
- 检查用户角色是否有权限访问该资源
|
||||
- 验证Casbin策略配置是否正确
|
||||
- 确认请求的资源和操作是否匹配策略
|
||||
|
||||
3. **登录失败**:
|
||||
- 检查用户名/邮箱和密码是否正确
|
||||
- 确认用户账户状态是否正常(未被禁用)
|
||||
- 检查数据库连接是否正常
|
||||
|
||||
4. **令牌刷新失败**:
|
||||
- 确认旧令牌是否有效
|
||||
- 检查客户端令牌是否匹配
|
||||
- 验证用户是否有权限选择指定的角色
|
||||
|
||||
**Section sources**
|
||||
- [auth.go](file://internal/middleware/auth.go)
|
||||
- [auth_handler.go](file://internal/handler/auth_handler.go)
|
||||
- [token_service.go](file://internal/service/token_service.go)
|
||||
|
||||
## 结论
|
||||
CarrotSkin项目实现了一套完整且安全的认证与授权机制,通过JWT和Casbin的结合,提供了灵活的用户身份验证和细粒度的权限控制。系统的分层架构使得各个组件职责清晰,易于维护和扩展。对于初学者,系统提供了清晰的API文档和错误处理机制;对于经验丰富的开发者,系统提供了扩展权限模型和集成其他认证方式的可能性。整体而言,CarrotSkin的安全机制设计合理,能够有效保护系统资源,为用户提供安全可靠的服务。
|
||||
Reference in New Issue
Block a user