访问控制 #
一、访问控制概述 #
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