第四天核心任务:表设计、接口文档、权限体系搭建、认证落地
首先我们确定了技术选型:Golang + docker + 社区版配置中心 + min.io(文件存储)+ PgSQL(关系型数据库)+ Redis + Neo4j(记忆图谱)+docker-compse+ansible+shell+python
项目模块分配:我负责用户权限管理及文档列表
主要任务:表设计,接口文档设计,实现方案等
一、模块概述:用户权限管理的核心目标
用户权限管理模块需实现三大核心功能:
- 用户 - 角色 - 权限的关联管理:通过多表关联实现灵活的权限分配
- 接口级权限校验:每个接口请求需经过权限验证,确保合法访问
- 身份认证与会话管理:基于 JWT 实现无状态的用户身份验证
同时需支撑文档列表模块的权限控制(如 "谁能查看 / 编辑哪些文档"),因此设计时需预留与业务模块的权限关联扩展点。
二、数据模型设计:五表联动的权限体系
为实现 "用户 - 角色 - 权限" 的多对多关系,设计五张核心表,形成完整的权限数据链路:
表名 | 作用 | 核心字段 |
---|---|---|
tb_user |
存储用户基础信息 | id (用户 ID)、username (用户名)、password_hash (密码哈希) |
tb_role |
定义角色类型(如管理员、普通用户) | id (角色 ID)、role_name (角色名称)、description (描述) |
tb_user_role_ref |
用户与角色的关联映射 | id 、user_id (关联用户)、role_id (关联角色) |
tb_permission |
定义权限点(如 "文档编辑""用户管理") | id 、perm_key (权限标识,如doc:edit )、description |
tb_role_permission |
角色与权限的关联映射 | id 、role_id (关联角色)、perm_id (关联权限) |
设计逻辑:
- 一个用户对应一个角色(如 "管理员 + 编辑"),通过
tb_user_role_ref
关联 - 一个角色可包含多个权限(如 "管理员" 包含所有权限),通过
tb_role_permission
关联 - 权限点与接口一一对应(如接口
/files/upload
对应权限file:upload
)
三、权限控制流程:从请求到响应的校验链路
通过时序图梳理权限校验的完整流程:

四、JWT 认证实现:无状态的身份验证
基于 JWT(JSON Web Token)实现用户身份认证,核心代码如下:
登录时生成JWT令牌
Go
// Claims JWT声明结构
type Claims struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
Role string `json:"role"`
jwt.RegisteredClaims
}
// GenerateToken 生成JWT令牌
func GenerateToken(userID int64, username, role string) (string, error) {
cfg := config.GetConfig()
claims := Claims{
UserID: userID,
Username: username,
Role: role,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Duration(cfg.JWT.ExpireTime) * time.Second)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(cfg.JWT.Secret))
}
func main() {
token, _ := GenerateToken(10000, "zhudayang", "admin")
fmt.Println(token)
}
// ParseToken 解析JWT令牌
func ParseToken(tokenString string) (*Claims, error) {
cfg := config.GetConfig()
token, err := jwt.ParseWithClaims(tokenString, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(cfg.JWT.Secret), nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*Claims); ok && token.Valid {
return claims, nil
}
return nil, errors.New("invalid token")
}
// RefreshToken 刷新令牌
func RefreshToken(tokenString string) (string, error) {
claims, err := ParseToken(tokenString)
if err != nil {
return "", err
}
// 生成新令牌
return GenerateToken(claims.UserID, claims.Username, claims.Role)
}
解析JWT令牌:
Go
// Auth 认证中间件
func Auth() gin.HandlerFunc {
return func(c *gin.Context) {
// 获取Authorization头
authHeader := c.GetHeader("Authorization")
if authHeader == "" {
stackTrace := getStackTrace()
logger.Error(fmt.Sprintf(
" | Authorization缺失 - method: %s | path: %s | client_ip: %s | user_agent: %s\nStack trace:\n%s",
c.Request.Method,
c.Request.URL.Path,
c.ClientIP(),
c.Request.UserAgent(),
stackTrace,
))
response.Unauthorized(c, "Authorization header is required")
c.Abort()
return
}
// 检查Bearer前缀
parts := strings.Split(authHeader, " ")
if len(parts) != 2 || parts[0] != "Bearer" {
stackTrace := getStackTrace()
logger.Error(fmt.Sprintf(
" | 无效token - method: %s | path: %s | client_ip: %s | auth_header: %s\nStack trace:\n%s",
c.Request.Method,
c.Request.URL.Path,
c.ClientIP(),
authHeader,
stackTrace,
))
response.Unauthorized(c, "Invalid authorization header format")
c.Abort()
return
}
token := parts[1]
// 解析JWT令牌
claims, err := auth.ParseToken(token)
if err != nil {
stackTrace := getStackTrace()
logger.Error(fmt.Sprintf(
" | 解析JWT令牌 - method: %s | path: %s | client_ip: %s | error: %s\nStack trace:\n%s",
c.Request.Method,
c.Request.URL.Path,
c.ClientIP(),
err.Error(),
stackTrace,
))
response.Unauthorized(c, "token is expired")
c.Abort()
return
}
// 将用户信息存储到上下文中
c.Set("user_id", claims.UserID)
c.Set("username", claims.Username)
c.Set("role", claims.Role)
// 记录认证成功
logger.Info(fmt.Sprintf(
" | 认证成功 - method: %s | path: %s | client_ip: %s | user_id: %d | username: %s | role: %s",
c.Request.Method,
c.Request.URL.Path,
c.ClientIP(),
claims.UserID,
claims.Username,
claims.Role,
))
c.Next()
}
}
六、总结与次日计划
第四天成果
- 完成用户权限管理模块的五表数据模型设计,明确 "用户 - 角色 - 权限" 的关联逻辑
- 梳理权限校验流程,通过时序图固化接口请求的权限判断链路
- 实现 JWT 令牌生成功能,为身份认证提供核心支撑