访问控制 #

一、访问控制概述 #

1.1 安全模型 #

text
FaunaDB安全模型:
├── 密钥(Key)
│   └── 认证凭证
├── 角色(Role)
│   └── 权限集合
├── 令牌(Token)
│   └── 用户会话
└── ABAC
    └── 基于属性的访问控制

1.2 权限层级 #

text
权限层级:
├── 内置角色
│   ├── Admin
│   ├── Server
│   ├── Server-ReadOnly
│   └── Client
└── 自定义角色
    └── 细粒度权限

二、密钥管理 #

2.1 密钥类型 #

类型 权限 用途
Admin 完全管理权限 数据库管理
Server 数据库完全访问 后端服务
Server-ReadOnly 只读访问 分析、报表
Client 受限访问 前端应用

2.2 创建密钥 #

javascript
// 创建Admin密钥
CreateKey({
  role: "admin"
})

// 创建Server密钥
CreateKey({
  role: "server",
  database: Database("my_database")
})

// 创建自定义角色密钥
CreateKey({
  role: Role("custom_role"),
  database: Database("my_database")
})

2.3 密钥管理 #

javascript
// 列出所有密钥
Paginate(Keys())

// 获取密钥信息
Get(Ref(Keys(), "key_id"))

// 删除密钥
Delete(Ref(Keys(), "key_id"))

2.4 密钥最佳实践 #

text
密钥安全建议:
├── 不要在客户端暴露Server密钥
├── 使用环境变量存储密钥
├── 定期轮换密钥
├── 为不同环境使用不同密钥
└── 删除不再使用的密钥

三、角色管理 #

3.1 创建角色 #

javascript
// 创建基本角色
CreateRole({
  name: "user_role",
  privileges: [
    {
      resource: Collection("users"),
      actions: {
        read: true,
        write: true
      }
    },
    {
      resource: Collection("posts"),
      actions: {
        read: true,
        create: true,
        write: Query(
          Lambda("ref",
            Equals(
              Select(["data", "authorId"], Get(Var("ref"))),
              CurrentIdentity()
            )
          )
        )
      }
    }
  ]
})

3.2 角色权限 #

javascript
// 完整的角色定义
CreateRole({
  name: "editor_role",
  privileges: [
    // 集合权限
    {
      resource: Collection("articles"),
      actions: {
        create: true,
        read: true,
        write: Query(
          Lambda("ref",
            Equals(
              Select(["data", "authorId"], Get(Var("ref"))),
              CurrentIdentity()
            )
          )
        ),
        delete: Query(
          Lambda("ref",
            Equals(
              Select(["data", "authorId"], Get(Var("ref"))),
              CurrentIdentity()
            )
          )
        ),
        history_read: false,
        history_write: false
      }
    },
    // 索引权限
    {
      resource: Index("articles_by_author"),
      actions: {
        read: true
      }
    },
    // 函数权限
    {
      resource: Function("create_article"),
      actions: {
        call: true
      }
    }
  ],
  membership: [
    {
      resource: Collection("users")
    }
  ]
})

3.3 角色操作 #

javascript
// 获取角色
Get(Role("user_role"))

// 列出所有角色
Paginate(Roles())

// 更新角色
Update(Role("user_role"), {
  privileges: [
    // 新的权限配置
  ]
})

// 删除角色
Delete(Role("old_role"))

四、ABAC权限控制 #

4.1 基于谓词的权限 #

javascript
// 谓词权限
CreateRole({
  name: "document_owner",
  privileges: [
    {
      resource: Collection("documents"),
      actions: {
        read: Query(
          Lambda("ref",
            Let(
              {
                doc: Get(Var("ref")),
                owner: Select(["data", "ownerId"], Var("doc")),
                currentUser: CurrentIdentity()
              },
              Or(
                Equals(Var("owner"), Var("currentUser")),
                HasRole(Role("admin"))
              )
            )
          )
        ),
        write: Query(
          Lambda("ref",
            Equals(
              Select(["data", "ownerId"], Get(Var("ref"))),
              CurrentIdentity()
            )
          )
        )
      }
    }
  ]
})

4.2 条件权限 #

javascript
// 条件权限
CreateRole({
  name: "premium_user",
  privileges: [
    {
      resource: Collection("premium_content"),
      actions: {
        read: Query(
          Lambda("ref",
            Let(
              {
                user: Get(CurrentIdentity()),
                subscription: Select(["data", "subscription"], Var("user"), "free"),
                expiresAt: Select(["data", "subscriptionExpiresAt"], Var("user"), Time("1970-01-01T00:00:00Z"))
              },
              And(
                Equals(Var("subscription"), "premium"),
                GT(Var("expiresAt"), Now())
              )
            )
          )
        )
      }
    }
  ]
})

4.3 数据过滤权限 #

javascript
// 基于数据的权限
CreateRole({
  name: "regional_manager",
  privileges: [
    {
      resource: Collection("stores"),
      actions: {
        read: Query(
          Lambda("ref",
            Let(
              {
                store: Get(Var("ref")),
                storeRegion: Select(["data", "region"], Var("store")),
                user: Get(CurrentIdentity()),
                userRegion: Select(["data", "region"], Var("user"))
              },
              Equals(Var("storeRegion"), Var("userRegion"))
            )
          )
        )
      }
    }
  ]
})

五、令牌管理 #

5.1 创建令牌 #

javascript
// 创建用户令牌
Create(Tokens(), {
  instance: Ref(Collection("users"), "user_001")
})

// 带过期时间的令牌
Create(Tokens(), {
  instance: Ref(Collection("users"), "user_001"),
  ttl: TimeAdd(Now(), 7, "day")
})

5.2 令牌操作 #

javascript
// 列出令牌
Paginate(Tokens())

// 删除令牌
Delete(Ref(Tokens(), "token_id"))

// 获取当前身份
CurrentIdentity()

// 检查是否有角色
HasRole(Role("admin"))

5.3 用户登录 #

javascript
// 登录函数
CreateFunction({
  name: "login",
  role: Role("server"),
  body: Query(
    Lambda(["email", "password"],
      Let(
        {
          user: Get(Match(Index("users_by_email"), Var("email"))),
          userRef: Select(["ref"], Var("user")),
          credential: Get(Match(Index("credentials_by_user"), Var("userRef")))
        },
        If(
          Equals(Select(["data", "password"], Var("credential")), Var("password")),
          Create(Tokens(), {
            instance: Var("userRef"),
            ttl: TimeAdd(Now(), 7, "day")
          }),
          Abort("Invalid credentials")
        )
      )
    )
  )
})

六、实际应用示例 #

6.1 多租户权限 #

javascript
// 租户角色
CreateRole({
  name: "tenant_member",
  privileges: [
    {
      resource: Collection("tenant_data"),
      actions: {
        read: Query(
          Lambda("ref",
            Equals(
              Select(["data", "tenantId"], Get(Var("ref"))),
              Select(["data", "tenantId"], Get(CurrentIdentity()))
            )
          )
        ),
        write: Query(
          Lambda("ref",
            Equals(
              Select(["data", "tenantId"], Get(Var("ref"))),
              Select(["data", "tenantId"], Get(CurrentIdentity()))
            )
          )
        )
      }
    }
  ]
})

6.2 内容管理权限 #

javascript
// 内容管理角色
CreateRole({
  name: "content_manager",
  privileges: [
    // 文章权限
    {
      resource: Collection("articles"),
      actions: {
        create: true,
        read: true,
        write: Query(
          Lambda("ref",
            Or(
              Equals(
                Select(["data", "authorId"], Get(Var("ref"))),
                CurrentIdentity()
              ),
              HasRole(Role("admin"))
            )
          )
        ),
        delete: Query(
          Lambda("ref",
            Or(
              And(
                Equals(
                  Select(["data", "authorId"], Get(Var("ref"))),
                  CurrentIdentity()
                ),
                Equals(Select(["data", "status"], Get(Var("ref"))), "draft")
              ),
              HasRole(Role("admin"))
            )
          )
        )
      }
    },
    // 媒体权限
    {
      resource: Collection("media"),
      actions: {
        create: true,
        read: true,
        delete: Query(
          Lambda("ref",
            Equals(
              Select(["data", "uploadedBy"], Get(Var("ref"))),
              CurrentIdentity()
            )
          )
        )
      }
    }
  ]
})

6.3 API访问控制 #

javascript
// API访问角色
CreateRole({
  name: "api_user",
  privileges: [
    // 只允许调用特定函数
    {
      resource: Function("api_get_products"),
      actions: { call: true }
    },
    {
      resource: Function("api_create_order"),
      actions: { call: true }
    },
    {
      resource: Function("api_get_orders"),
      actions: { call: true }
    }
  ],
  membership: [
    {
      resource: Collection("api_clients")
    }
  ]
})

七、权限最佳实践 #

7.1 最小权限原则 #

javascript
// 只授予必要的权限
CreateRole({
  name: "order_reader",
  privileges: [
    {
      resource: Collection("orders"),
      actions: {
        read: true  // 只读权限
      }
    },
    {
      resource: Index("orders_by_user"),
      actions: {
        read: true
      }
    }
  ]
})

7.2 分离关注点 #

javascript
// 分离读写角色
CreateRole({
  name: "data_reader",
  privileges: [
    {
      resource: Collection("analytics"),
      actions: { read: true }
    }
  ]
})

CreateRole({
  name: "data_writer",
  privileges: [
    {
      resource: Collection("analytics"),
      actions: { create: true }
    }
  ]
})

7.3 审计日志 #

javascript
// 带审计的操作
CreateFunction({
  name: "secure_delete",
  role: Role("admin"),
  body: Query(
    Lambda("ref",
      Do(
        // 记录审计日志
        Create(Collection("audit_logs"), {
          data: {
            action: "delete",
            resource: Var("ref"),
            user: CurrentIdentity(),
            timestamp: Now()
          }
        }),
        // 执行删除
        Delete(Var("ref"))
      )
    )
  )
})

八、总结 #

访问控制要点:

组件 说明
Key 认证密钥
Role 权限角色
Token 会话令牌
ABAC 基于属性的访问控制
谓词 条件权限

下一步,让我们学习时间旅行!

最后更新:2026-03-27