# 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实现。**
