# vbase 用户权限系统重构设计 ## 一、设计原则 1. **标准化**:遵循 OAuth2.0 / OIDC 标准协议 2. **无状态**:服务无状态,水平扩展友好 3. **安全性**:密码bcrypt、JWT签名、HTTPS强制 4. **性能**:Redis缓存热点数据,1分钟TTL自动刷新 5. **可维护性**:清晰分层,单一职责 --- ## 二、系统架构 ``` ┌─────────────────────────────────────────────────────────────┐ │ 接入层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ REST API │ │ OAuth2.0 │ │ OIDC Discovery │ │ │ └──────┬──────┘ └──────┬──────┘ └──────────┬──────────┘ │ └─────────┼────────────────┼────────────────────┼────────────┘ │ │ │ ┌─────────▼────────────────▼────────────────────▼────────────┐ │ 服务层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ Auth服务 │ │ Org服务 │ │ OAuth服务 │ │ │ │ (认证) │ │ (组织) │ │ (第三方接入) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ User服务 │ │ Role服务 │ │ Permission服务 │ │ │ │ (用户) │ │ (角色) │ │ (权限) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ ┌─────────▼──────────────────────────────────────────────────┐ │ 数据层 │ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ │ MySQL/PSQL │ │ Redis │ │ (可选)Etcd │ │ │ │ (主存储) │ │ (缓存/会话) │ │ (配置中心) │ │ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ ``` --- ## 三、核心数据模型 ### 3.1 身份认证模型 ```go // User - 全局用户表 // 一个用户可属于多个组织,但登录是全局的 type User struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` Username string `json:"username" gorm:"uniqueIndex;size:50;not null"` Password string `json:"-" gorm:"size:255"` // bcrypt hash,第三方登录可为空 Nickname string `json:"nickname" gorm:"size:50"` Avatar string `json:"avatar" gorm:"size:500"` Email string `json:"email" gorm:"uniqueIndex;size:100"` Phone string `json:"phone" gorm:"uniqueIndex;size:20"` Status int `json:"status" gorm:"default:1"` // 0:禁用 1:正常 2:未激活 EmailVerified bool `json:"email_verified" gorm:"default:false"` PhoneVerified bool `json:"phone_verified" gorm:"default:false"` LastLoginAt *time.Time `json:"last_login_at"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` } // Identity - 第三方身份绑定 // 支持多种登录方式绑定到同一账号 type Identity struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` UserID string `json:"user_id" gorm:"index;not null"` Provider string `json:"provider" gorm:"size:20;not null"` // google/github/wechat/ldap ProviderUID string `json:"provider_uid" gorm:"index;size:100;not null"` // 第三方唯一ID ProviderName string `json:"provider_name" gorm:"size:50"` Avatar string `json:"avatar" gorm:"size:500"` Email string `json:"email" gorm:"size:100"` AccessToken string `json:"-" gorm:"size:500"` // 加密存储 RefreshToken string `json:"-" gorm:"size:500"` ExpiresAt *time.Time `json:"-"` CreatedAt time.Time `json:"created_at"` } // Session - 登录会话 // 用于多端登录管理和撤销 type Session struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` UserID string `json:"user_id" gorm:"index;not null"` TokenID string `json:"token_id" gorm:"uniqueIndex;size:36"` // JWT jti Type string `json:"type" gorm:"size:20;not null"` // access/refresh DeviceInfo string `json:"device_info" gorm:"size:200"` IP string `json:"ip" gorm:"size:50"` ExpiresAt time.Time `json:"expires_at"` Revoked bool `json:"revoked" gorm:"default:false"` RevokedAt *time.Time `json:"revoked_at"` CreatedAt time.Time `json:"created_at"` } ``` ### 3.2 组织架构模型 ```go // Org - 组织/租户 // 完全隔离的数据边界 type Org struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` Name string `json:"name" gorm:"size:50;not null"` Code string `json:"code" gorm:"uniqueIndex;size:30;not null"` // 组织唯一编码 OwnerID string `json:"owner_id" gorm:"not null"` // 创建者/所有者 // 树形结构 ParentID *string `json:"parent_id" gorm:"index"` Path string `json:"path" gorm:"size:500;index"` // 完整路径 /root/tech/backend Level int `json:"level" gorm:"default:0"` // 配置 Description string `json:"description" gorm:"size:200"` Logo string `json:"logo" gorm:"size:500"` Settings string `json:"-" gorm:"type:text"` // JSON配置 // 状态 Status int `json:"status" gorm:"default:1"` // 0:禁用 1:正常 MaxMembers int `json:"max_members" gorm:"default:100"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // OrgMember - 组织成员关系 // 用户与组织的多对多关系 type OrgMember struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` OrgID string `json:"org_id" gorm:"uniqueIndex:idx_org_user;not null"` UserID string `json:"user_id" gorm:"uniqueIndex:idx_org_user;not null"` // 角色(多个角色,逗号分隔) RoleIDs string `json:"role_ids" gorm:"size:200"` // 成员信息 Position string `json:"position" gorm:"size:50"` // 职位 Department string `json:"department" gorm:"size:50"` // 部门名称(冗余) JoinedAt time.Time `json:"joined_at"` // 状态 0:待审核 1:正常 2:禁用 Status int `json:"status" gorm:"default:1"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } ``` ### 3.3 权限模型(RBAC + ABAC) ```go // Role - 角色 // 组织级别的角色定义 type Role struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` OrgID string `json:"org_id" gorm:"index;not null"` Code string `json:"code" gorm:"size:50;not null"` // 角色编码 Name string `json:"name" gorm:"size:50;not null"` Description string `json:"description" gorm:"size:200"` // 关联策略 PolicyIDs string `json:"policy_ids" gorm:"type:text"` // 逗号分隔 // 属性 IsDefault bool `json:"is_default" gorm:"default:false"` // 新成员默认角色 IsSystem bool `json:"is_system" gorm:"default:false"` // 系统内置(不可删) SortOrder int `json:"sort_order" gorm:"default:0"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // Policy - 策略 // 细粒度权限定义,支持ABAC type Policy struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` OrgID string `json:"org_id" gorm:"index"` // 空表示全局策略 Code string `json:"code" gorm:"uniqueIndex;size:50;not null"` Name string `json:"name" gorm:"size:50;not null"` Description string `json:"description" gorm:"size:200"` // 资源定义 Resource string `json:"resource" gorm:"size:50;not null"` // 资源类型: user/org/member/role等 Action string `json:"action" gorm:"size:20;not null"` // read/create/update/delete/* /batch_create等 // ABAC条件(CEL表达式) // 示例: "resource.owner == user.id" - 只能操作自己的资源 // 示例: "user.roles.exists(r, r == 'admin')" - 需要admin角色 // 示例: "resource.org_id == org.id" - 只能操作当前组织的资源 Condition string `json:"condition" gorm:"type:text"` // 效果: allow/deny(deny优先) Effect string `json:"effect" gorm:"size:10;default:allow"` // 优先级(数字越大优先级越高,deny策略建议高优先级) Priority int `json:"priority" gorm:"default:0"` IsSystem bool `json:"is_system" gorm:"default:false"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } ``` ### 3.4 OAuth2.0 模型 ```go // OAuthClient - 注册的应用客户端 type OAuthClient struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` Name string `json:"name" gorm:"size:50;not null"` Description string `json:"description" gorm:"size:200"` // 客户端凭证 ClientID string `json:"client_id" gorm:"uniqueIndex;size:32;not null"` ClientSecret string `json:"-" gorm:"size:64;not null"` // OAuth配置 RedirectURIs string `json:"redirect_uris" gorm:"type:text"` // 逗号分隔 GrantTypes string `json:"grant_types" gorm:"size:100"` // authorization_code/refresh_token/client_credentials ResponseTypes string `json:"response_types" gorm:"size:50"` // code/token // 访问控制 AllowedScopes string `json:"allowed_scopes" gorm:"size:200"` // openid profile email org roles TokenExpiry int `json:"token_expiry" gorm:"default:3600"` // access_token有效期(秒) RefreshExpiry int `json:"refresh_expiry" gorm:"default:2592000"` // refresh_token有效期(秒) // 归属 OwnerID string `json:"owner_id" gorm:"not null"` OrgID string `json:"org_id" gorm:"index"` // 可选,绑定特定组织 // 状态 0:禁用 1:正常 Status int `json:"status" gorm:"default:1"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // OAuthAuthorization - 授权码存储 type OAuthAuthorization struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` UserID string `json:"user_id" gorm:"index;not null"` ClientID string `json:"client_id" gorm:"index;not null"` OrgID string `json:"org_id" gorm:"index"` // 授权信息 Code string `json:"code" gorm:"uniqueIndex;size:64"` Scope string `json:"scope" gorm:"size:200"` State string `json:"state" gorm:"size:100"` // PKCE CodeChallenge string `json:"-" gorm:"size:128"` CodeChallengeMethod string `json:"-" gorm:"size:10"` // 状态 Used bool `json:"used" gorm:"default:false"` UsedAt *time.Time `json:"used_at"` ExpiresAt time.Time `json:"expires_at"` CreatedAt time.Time `json:"created_at"` } // OAuthToken - OAuth访问令牌 type OAuthToken struct { ID string `json:"id" gorm:"primaryKey;type:varchar(36)"` UserID string `json:"user_id" gorm:"index;not null"` ClientID string `json:"client_id" gorm:"index;not null"` OrgID string `json:"org_id" gorm:"index"` // Token信息 AccessToken string `json:"-" gorm:"uniqueIndex;size:64"` RefreshToken string `json:"-" gorm:"uniqueIndex;size:64"` TokenType string `json:"token_type" gorm:"size:10;default:Bearer"` Scope string `json:"scope" gorm:"size:200"` // 有效期 ExpiresAt time.Time `json:"expires_at"` Revoked bool `json:"revoked" gorm:"default:false"` RevokedAt *time.Time `json:"revoked_at"` CreatedAt time.Time `json:"created_at"` } ``` --- ## 四、API 设计 ### 4.1 路由结构 ``` /api/v1 ├── /auth # 认证相关(公开或需基础认证) │ ├── POST /login │ ├── POST /logout │ ├── POST /refresh │ ├── POST /register │ ├── POST /forgot-password │ ├── POST /reset-password │ ├── GET /captcha │ ├── GET /oauth/:provider # 第三方登录跳转 │ ├── GET /oauth/:provider/callback │ └── POST /oauth/bind │ ├── /me # 当前用户(需认证) │ ├── GET / │ ├── PATCH / │ ├── GET /sessions # 登录会话列表 │ ├── DELETE /sessions/:id # 撤销会话 │ ├── GET /identities # 绑定的第三方账号 │ ├── DELETE /identities/:provider # 解绑 │ ├── GET /orgs # 我的组织列表 │ └── POST /change-password │ ├── /users # 用户管理(需权限) │ ├── GET / │ ├── POST / │ ├── GET /:id │ ├── PATCH /:id │ ├── DELETE /:id │ └── PATCH /:id/status │ ├── /orgs # 组织管理 │ ├── GET / # 列表 │ ├── POST / # 创建(需登录) │ ├── GET /:id │ ├── PATCH /:id # 需组织管理员权限 │ ├── DELETE /:id │ ├── GET /:id/tree # 组织树 │ ├── GET /:id/members # 成员列表 │ ├── POST /:id/members # 邀请成员 │ ├── GET /:id/members/:user_id │ ├── PATCH /:id/members/:user_id # 修改角色/状态 │ ├── DELETE /:id/members/:user_id │ ├── GET /:id/roles # 组织角色 │ ├── POST /:id/roles │ └── GET /:id/policies # 组织策略 │ ├── /roles # 角色管理(需组织上下文) │ ├── GET / │ ├── POST / │ ├── GET /:id │ ├── PATCH /:id │ └── DELETE /:id │ ├── /policies # 策略管理 │ ├── GET / │ ├── POST / │ ├── GET /:id │ ├── PATCH /:id │ └── DELETE /:id │ ├── /oauth # OAuth2.0 服务端 │ ├── GET /authorize # 授权端点 │ ├── POST /token # 令牌端点 │ ├── POST /revoke # 撤销令牌 │ ├── GET /userinfo # 用户信息 │ ├── GET /.well-known/openid-configuration │ ├── GET /.well-known/jwks.json │ │ │ └── /clients # 客户端管理(需认证) │ ├── GET / │ ├── POST / │ ├── GET /:id │ ├── PATCH /:id │ ├── DELETE /:id │ └── POST /:id/reset-secret │ └── /check # 权限检查(内部服务调用) └── POST /permission # 检查指定权限 ``` ### 4.2 认证相关 API #### POST /api/v1/auth/login 账号密码登录 ```json // Request { "username": "string", // 用户名/邮箱/手机号 "password": "string", "captcha_id": "string", // 可选,错误多次后需要 "captcha_code": "string", "remember": false // 是否长效token } // Response 200 { "access_token": "eyJhbGciOiJSUzI1NiIs...", "refresh_token": "dGhpcyBpcyBhIHJlZnJlc2g...", "token_type": "Bearer", "expires_in": 3600, "user": { "id": "uuid", "username": "john", "nickname": "John Doe", "email": "john@example.com", "avatar": "https://..." } } ``` #### POST /api/v1/auth/oauth/:provider 第三方登录,返回跳转URL或直接302跳转 ```json // Query Params ?redirect_uri=https://app.com/callback&state=xyz // Response (如果是SPA,返回URL) { "auth_url": "https://accounts.google.com/o/oauth2/v2/auth..." } ``` #### POST /api/v1/auth/oauth/bind 绑定第三方账号到已有账号 ```json // Request { "provider": "google", "code": "authorization_code_from_provider", "bind_type": "register" | "login", // 新注册还是绑定已有 "username": "string", // bind_type=register时需要 "password": "string" // bind_type=login时需要 } // Response { "access_token": "...", "user": {...} } ``` ### 4.3 组织相关 API #### GET /api/v1/orgs 获取组织列表(用户加入的) ```json // Response { "items": [ { "id": "uuid", "name": "技术部", "code": "tech", "logo": "https://...", "owner_id": "uuid", "member_count": 25, "my_roles": ["admin", "developer"], "joined_at": "2024-01-15T10:30:00Z" } ] } ``` #### POST /api/v1/orgs 创建组织 ```json // Request { "name": "新产品线", "code": "new-product", // 唯一编码 "description": "...", "logo": "https://..." } // Response { "id": "uuid", "name": "新产品线", "code": "new-product", "owner_id": "current_user_id", // 自动创建owner角色并分配 } ``` **注意**:创建者自动成为组织所有者(owner),拥有所有权限。 ### 4.4 权限相关 API #### GET /api/v1/check/permissions 获取当前用户在指定组织的所有权限(用于前端按钮控制) ```json // Query Params ?org_id=xxx // Response { "org_id": "uuid", "roles": ["admin", "developer"], "permissions": [ "user:read", "user:update:own", "org:read", "member:manage", "role:read" ] } ``` #### POST /api/v1/check/permission 检查具体权限(其他服务调用) ```json // Request { "org_id": "uuid", "resource": "user", "action": "update", "resource_id": "target_user_id" // 可选 } // Response { "allowed": true, "reason": "用户是资源所有者" } ``` --- ## 五、权限系统设计 ### 5.1 策略表达式(CEL) 使用 [CEL (Common Expression Language)](https://github.com/google/cel-go) 作为条件表达式语言。 ```go // 内置变量 user // 当前用户对象 org // 当前组织对象 resource // 被访问资源对象 action // 动作: read/create/update/delete // 示例策略条件 "true" // 无条件允许 "resource.created_by == user.id" // 只能操作自己创建的资源 "resource.owner_id == user.id" // 资源所有者 "org.members.exists(m, m.user_id == user.id && m.roles.exists(r, r.code == 'admin'))" "user.id in org.owners" // 组织所有者 "resource.org_id == org.id" // 只能访问当前组织的资源 "resource.status == 'pending' && action == 'update'" // 特定状态才允许操作 ``` ### 5.2 系统内置策略 | 编码 | 资源 | 动作 | 条件 | 效果 | 说明 | |------|------|------|------|------|------| | `sys:user:read:own` | user | read | `resource.id == user.id` | allow | 读自己 | | `sys:user:update:own` | user | update | `resource.id == user.id` | allow | 改自己 | | `sys:org:admin` | org | * | `org.owner_id == user.id` | allow | 组织所有者 | | `sys:member:read` | member | read | `resource.org_id == org.id` | allow | 读成员 | | `sys:member:manage` | member | * | 需自定义角色 | allow | 管理成员 | | `sys:role:read` | role | read | `resource.org_id == org.id` | allow | 读角色 | | `sys:role:manage` | role | * | 需自定义角色 | allow | 管理角色 | ### 5.3 权限检查流程 ```go // 中间件流程 func PermissionMiddleware(resource, action string) vigo.Middleware { return func(x *vigo.X) error { // 1. 获取当前用户 user := auth.CurrentUser(x) if user == nil { return vigo.ErrUnauthorized } // 2. 获取当前组织(从Header或Query) orgID := x.Request.Header.Get("X-Org-ID") if orgID == "" { orgID = x.Query("org_id") } // 3. 构建缓存key cacheKey := fmt.Sprintf("perm:%s:%s:%s:%s", user.ID, orgID, resource, action) // 4. 查缓存 if cached, err := redis.Get(cacheKey); err == nil { if cached == "deny" { return vigo.ErrForbidden } x.Set("permission_checked", true) return x.Next() } // 5. 查询用户在该组织的角色 member := getOrgMember(orgID, user.ID) if member == nil { redis.Set(cacheKey, "deny", 1*time.Minute) return vigo.ErrForbidden } // 6. 收集所有策略 policies := getPoliciesByRoles(member.RoleIDs) // 7. 评估策略 allowed := evaluatePolicies(policies, user, org, resource, action) // 8. 写入缓存 if allowed { redis.Set(cacheKey, "allow", 1*time.Minute) } else { redis.Set(cacheKey, "deny", 1*time.Minute) } if !allowed { return vigo.ErrForbidden } return x.Next() } } ``` --- ## 六、OAuth2.0 / OIDC 实现 ### 6.1 支持的授权流程 1. **Authorization Code Flow**(推荐,支持PKCE) - 用于服务端应用 - 支持 `code_challenge` (PKCE) 2. **Implicit Flow**(不推荐,但为了兼容支持) - 用于纯前端应用(建议迁移到PKCE) 3. **Client Credentials Flow** - 用于服务间调用 4. **Refresh Token** - 用于刷新 access_token ### 6.2 OIDC 支持 - `/.well-known/openid-configuration` - 发现端点 - `/.well-known/jwks.json` - 公钥获取 - Scope: `openid profile email org roles` - ID Token: JWT格式,包含用户基本信息 ### 6.3 授权流程示例 ``` ┌─────────────┐ ┌─────────────┐ │ 第三方应用 │ │ vbase │ └──────┬──────┘ └──────┬──────┘ │ │ │ 1. GET /oauth/authorize? │ │ response_type=code& │ │ client_id=xxx& │ │ redirect_uri=xxx& │ │ scope=openid profile org& │ │ state=xxx& │ │ code_challenge=xxx& │ │ code_challenge_method=S256 │ ├─────────────────────────────────────────────────►│ │ │ │ 2. 未登录,重定向到登录页 │ │◄─────────────────────────────────────────────────┤ │ │ │ 3. 登录后,用户授权确认页面 │ │ (展示应用请求的权限范围) │ ├─────────────────────────────────────────────────►│ │ │ │ 4. 302 重定向到 redirect_uri │ │ ?code=xxx&state=xxx │ │◄─────────────────────────────────────────────────┤ │ │ │ 5. POST /oauth/token │ │ grant_type=authorization_code& │ │ code=xxx& │ │ redirect_uri=xxx& │ │ client_id=xxx& │ │ client_secret=xxx& │ │ code_verifier=xxx (PKCE) │ ├─────────────────────────────────────────────────►│ │ │ │ 6. 返回 Token │ │ { │ │ access_token: "...", │ │ id_token: "...", │ │ refresh_token: "...", │ │ token_type: "Bearer", │ │ expires_in: 3600 │ │ } │ │◄─────────────────────────────────────────────────┤ ``` --- ## 七、缓存策略 ### 7.1 Redis 缓存结构 ``` # 权限缓存(核心) key: perm:{user_id}:{org_id}:{resource}:{action} value: allow | deny ttl: 60秒 # 用户信息缓存 key: user:{user_id} value: JSON ttl: 300秒 # 组织信息缓存 key: org:{org_id} value: JSON ttl: 300秒 # 组织成员缓存 key: org:{org_id}:member:{user_id} value: JSON (包含角色ID列表) ttl: 60秒 # 角色策略缓存 key: role:{role_id}:policies value: JSON数组 ttl: 300秒 # Session/Token 黑名单(用于撤销) key: token:revoked:{jti} value: 1 ttl: 与token剩余有效期一致 # 限流计数 key: ratelimit:{ip}:{path} value: 计数 ttl: 60秒 # 验证码 key: captcha:{captcha_id} value: 验证码内容 ttl: 300秒 # OAuth 授权码 key: oauth:code:{code} value: 授权信息JSON ttl: 600秒 ``` ### 7.2 缓存更新策略 1. **被动失效**:数据变更时删除缓存 2. **主动刷新**:TTL到期自动重新加载 3. **权限缓存**:短TTL(1分钟),保证实时性 4. **配置缓存**:长TTL(5分钟),减少DB查询 --- ## 八、安全设计 ### 8.1 密码安全 - **算法**:bcrypt(cost=12) - **历史密码**:不允许重复使用最近5次密码 - **复杂度**:最小8位,包含大小写+数字 - **传输**:HTTPS only,前端bcrypt预哈希(可选) ### 8.2 Token安全 - **Access Token**:JWT RS256签名,有效期1小时 - **Refresh Token**:随机字符串,有效期30天,可撤销 - **Token绑定**:可选绑定设备指纹,防止盗用 - **撤销机制**:JWT jti 存入黑名单实现撤销 ### 8.3 OAuth安全 - **PKCE**:所有public client强制启用 - **State参数**:强制验证,防止CSRF - **Redirect URI**:必须预注册,严格匹配 - **Client Secret**:仅用于confidential client ### 8.4 防护措施 - **限流**: - 登录:5次/分钟,错误5次后需要验证码 - 注册:3次/小时 - API:100次/分钟/用户 - **验证码**: - 图形验证码:登录错误多次后 - 邮箱/短信验证码:密码重置、敏感操作 - **审计日志**: - 登录/登出 - 密码修改 - 权限变更 - 组织重要操作 --- ## 九、初始化流程 系统首次启动时自动执行: 1. **创建数据库表** 2. **创建超级管理员** - 检测用户表是否为空 - 为空时创建默认超管账号 - 用户名/密码从环境变量读取(或随机生成并打印日志) 3. **创建系统策略** - 创建所有系统内置策略 4. **创建默认组织**(可选) - 创建名为"Default"的根组织 - 将超管加入该组织 --- ## 十、技术选型 | 组件 | 选型 | 说明 | |------|------|------| | Web框架 | Vigo | 保持使用 | | ORM | GORM | 保持使用 | | 数据库 | MySQL/PostgreSQL | 保持使用 | | 缓存 | Redis | 必选 | | 密码哈希 | bcrypt | golang.org/x/crypto/bcrypt | | JWT | jwt-go / golang-jwt | 标准库 | | CEL表达式 | cel-go | github.com/google/cel-go | | 验证码 | base64Captcha | 或自研 | | OAuth2 | go-oauth2/oauth2 | 或自研实现 | --- ## 十一、目录结构 ``` / ├── cmd/ │ └── server/ │ └── main.go # 服务入口 ├── internal/ # 私有代码 │ ├── api/ # API层 │ │ ├── auth/ # 认证API │ │ ├── user/ # 用户API │ │ ├── org/ # 组织API │ │ ├── role/ # 角色API │ │ ├── policy/ # 策略API │ │ ├── oauth/ # OAuth2.0服务端 │ │ └── middleware/ # 中间件 │ │ ├── auth.go # 认证中间件 │ │ ├── permission.go # 权限中间件 │ │ ├── ratelimit.go # 限流中间件 │ │ └── cors.go # 跨域中间件 │ ├── service/ # 业务逻辑层 │ │ ├── auth.go │ │ ├── user.go │ │ ├── org.go │ │ ├── role.go │ │ ├── policy.go │ │ ├── permission.go # 权限检查核心 │ │ └── oauth.go │ ├── model/ # 数据模型 │ │ ├── user.go │ │ ├── org.go │ │ ├── role.go │ │ ├── policy.go │ │ ├── oauth.go │ │ └── migrate.go # 数据库迁移 │ ├── repository/ # 数据访问层 │ │ ├── user.go │ │ ├── org.go │ │ └── ... │ ├── cache/ # 缓存封装 │ │ └── redis.go │ ├── pkg/ # 内部工具包 │ │ ├── crypto/ # 加密工具 │ │ ├── jwt/ # JWT工具 │ │ ├── cel/ # CEL表达式 │ │ └── oauth/ # OAuth2工具 │ └── config/ # 配置 │ └── config.go ├── pkg/ # 可公开使用的包 │ └── sdk/ # 其他服务使用的SDK ├── docs/ # 文档 ├── scripts/ # 脚本 ├── configs/ # 配置文件 ├── go.mod └── README.md ``` --- ## 十二、开发计划 ### Phase 1: 基础架构 1. 数据库模型定义和迁移 2. Redis缓存封装 3. JWT认证中间件 4. 基础配置管理 ### Phase 2: 认证模块 1. 用户注册/登录/登出 2. 密码管理 3. Session管理 4. 验证码 ### Phase 3: 组织与成员 1. 组织CRUD 2. 成员管理 3. 组织树查询 ### Phase 4: 权限系统 1. 策略定义 2. 角色管理 3. 权限检查中间件 4. CEL表达式评估 ### Phase 5: OAuth2.0 1. 客户端管理 2. 授权流程 3. Token管理 4. OIDC支持 ### Phase 6: 第三方登录 1. Google/GitHub/微信登录 2. 账号绑定 ### Phase 7: 完善 1. 审计日志 2. 管理后台API 3. 测试和文档 --- **确认以上设计后,开始Phase 1实现。**